diff options
Diffstat (limited to 'lib/Service/FollowService.php')
-rw-r--r-- | lib/Service/FollowService.php | 157 |
1 files changed, 95 insertions, 62 deletions
diff --git a/lib/Service/FollowService.php b/lib/Service/FollowService.php index 47e1ce59..ee295e45 100644 --- a/lib/Service/FollowService.php +++ b/lib/Service/FollowService.php @@ -30,79 +30,118 @@ declare(strict_types=1); namespace OCA\Social\Service; -use OCA\Social\Tools\Exceptions\MalformedArrayException; -use OCA\Social\Tools\Traits\TArrayTools; +use ActivityPhp\Type; use OCA\Social\AP; -use OCA\Social\Db\FollowsRequest; -use OCA\Social\Exceptions\CacheActorDoesNotExistException; -use OCA\Social\Exceptions\FollowNotFoundException; -use OCA\Social\Exceptions\FollowSameAccountException; -use OCA\Social\Exceptions\InvalidOriginException; -use OCA\Social\Exceptions\InvalidResourceException; -use OCA\Social\Exceptions\ItemUnknownException; -use OCA\Social\Exceptions\RedundancyLimitException; -use OCA\Social\Tools\Exceptions\RequestContentException; -use OCA\Social\Tools\Exceptions\RequestNetworkException; -use OCA\Social\Tools\Exceptions\RequestResultNotJsonException; -use OCA\Social\Tools\Exceptions\RequestResultSizeException; -use OCA\Social\Tools\Exceptions\RequestServerException; -use OCA\Social\Exceptions\RetrieveAccountFormatException; -use OCA\Social\Exceptions\SocialAppConfigException; -use OCA\Social\Exceptions\UnauthorizedFediverseException; -use OCA\Social\Exceptions\UrlCloudException; -use OCA\Social\Model\ActivityPub\Activity\Undo; -use OCA\Social\Model\ActivityPub\Actor\Person; -use OCA\Social\Model\ActivityPub\Object\Follow; -use OCA\Social\Model\ActivityPub\OrderedCollection; -use OCA\Social\Model\InstancePath; +use OCA\Social\Entity\Account; +use OCA\Social\Entity\Follow; +use OCA\Social\Entity\FollowRequest; +use OCA\Social\Service\Feed\FeedManager; +use OCP\DB\ORM\IEntityManager; +use OCP\DB\ORM\IEntityRepository; + +class FollowOption { + /** + * Show reblog of the account + */ + public bool $showReblogs = true; -class FollowService { - use TArrayTools; + /** + * Notify about new posts + */ + public bool $notify = false; + static public function default(): self { + return new FollowOption(); + } +} - private FollowsRequest $followsRequest; +class FollowService { + private IEntityManager $entityManager; + /** @var IEntityRepository<Follow> $followRepository */ + private IEntityRepository $followRepository; + /** @var IEntityRepository<FollowRequest> $followRepository */ + private IEntityRepository $followRequestRepository; + private FeedManager $feedManager; + + public function __construct(IEntityManager $entityManager, FeedManager $feedManager) { + $this->entityManager = $entityManager; + $this->followRepository = $entityManager->getRepository(Follow::class); + $this->followRepository = $entityManager->getRepository(FollowRequest::class); + $this->feedManager = $feedManager; + } - private ActivityService $activityService; + public function follow(Account $sourceAccount, Account $targetAccount, FollowOption $option): void { + if ($sourceAccount->following($targetAccount)) { + $this->updateFollow($sourceAccount, $targetAccount, $option->notify, $option->showReblogs); + return; + } elseif ($sourceAccount->followRequested($targetAccount)) { + $this->updateFollowRequest($sourceAccount, $targetAccount, $option->notify, $option->showReblogs); + return; + } - private CacheActorService $cacheActorService; + if ($targetAccount->isLocked() || !$targetAccount->isLocal()) { + $this->requestFollow($sourceAccount, $targetAccount); + } else { + $this->directFollow($sourceAccount, $targetAccount); + } + } - private ConfigService $configService; + private function updateFollow(Account $sourceAccount, Account $targetAccount, bool $notify, bool $showReblogs): void { + /** @var Follow $follow */ + $follow = $this->followRepository->findOneBy([ + 'account' => $sourceAccount, + 'targetAccount' => $targetAccount, + ]); + assert($follow); + + $follow->setNotify($notify); + $follow->setShowReblogs($showReblogs); + $this->entityManager->persist($follow); + $this->entityManager->flush(); + } - private MiscService $miscService; + private function updateFollowRequest(Account $sourceAccount, Account $targetAccount, bool $notify, bool $showReblogs): void { + /** @var Follow $follow */ + $followRequest = $this->followRequestRepository->findOneBy([ + 'account' => $sourceAccount, + 'targetAccount' => $targetAccount, + ]); + assert($followRequest); + + $followRequest->setNotify($notify); + $followRequest->setShowReblogs($showReblogs); + $this->entityManager->persist($followRequest); + $this->entityManager->flush(); + } + private function directFollow(Account $sourceAccount, Account $targetAccount): Follow { + $follow = $sourceAccount->follow($targetAccount); + $this->entityManager->persist($sourceAccount); - private ?Person $viewer = null; + // TODO Notify target account they got a new follower + $this->feedManager->mergeIntoHome($targetAccount, $sourceAccount); - /** - * FollowService constructor. - * - * @param FollowsRequest $followsRequest - * @param ActivityService $activityService - * @param CacheActorService $cacheActorService - * @param ConfigService $configService - * @param MiscService $miscService - */ - public function __construct( - FollowsRequest $followsRequest, ActivityService $activityService, - CacheActorService $cacheActorService, ConfigService $configService, MiscService $miscService - ) { - $this->followsRequest = $followsRequest; - $this->activityService = $activityService; - $this->cacheActorService = $cacheActorService; - $this->configService = $configService; - $this->miscService = $miscService; + return $follow; } + private function requestFollow(Account $sourceAccount, Account $targetAccount) { + if ($targetAccount->isLocal()) { + // Just create an internal follow request - /** - * @param Person $viewer - */ - public function setViewer(Person $viewer) { - $this->viewer = $viewer; - $this->followsRequest->setViewer($viewer); + } else { + $this->createRemoteFollowRequest($sourceAccount, $targetAccount); + } } + private function createRemoteFollowRequest(Account $sourceAccount, Account $targetAccount): void { + /** @var Type\Extended\Activity\Follow $follow */ + $follow = Type::create('Follow', [ + '@context' => 'https://www.w3.org/ns/activitystreams', + 'actor' => $sourceAccount->getUri(), + 'object' => $targetAccount->getUri(), + ]); + } /** * @param Person $actor @@ -131,12 +170,6 @@ class FollowService { throw new FollowSameAccountException("Don't follow yourself, be your own lead"); } - /** @var Follow $follow */ - $follow = AP::$activityPub->getItemFromType(Follow::TYPE); - $follow->generateUniqueId(); - $follow->setActorId($actor->getId()); - $follow->setObjectId($remoteActor->getId()); - $follow->setFollowId($remoteActor->getFollowers()); try { $this->followsRequest->getByPersons($actor->getId(), $remoteActor->getId()); |