Skip to content

Commit

Permalink
Add peertube support (#782)
Browse files Browse the repository at this point in the history
Co-authored-by: debounced <[email protected]>
  • Loading branch information
BentiGorlich and debounced authored Jun 29, 2024
1 parent b3240c0 commit 4e43b06
Show file tree
Hide file tree
Showing 28 changed files with 343 additions and 81 deletions.
48 changes: 48 additions & 0 deletions migrations/Version20240614120443.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20240614120443 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add columns for remote likes, dislikes and shares';
}

public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE entry ADD ap_like_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE entry ADD ap_dislike_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE entry ADD ap_share_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE entry_comment ADD ap_like_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE entry_comment ADD ap_dislike_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE entry_comment ADD ap_share_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post ADD ap_like_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post ADD ap_dislike_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post ADD ap_share_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post_comment ADD ap_like_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post_comment ADD ap_dislike_count INT DEFAULT NULL');
$this->addSql('ALTER TABLE post_comment ADD ap_share_count INT DEFAULT NULL');
}

public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE entry_comment DROP ap_like_count');
$this->addSql('ALTER TABLE entry_comment DROP ap_dislike_count');
$this->addSql('ALTER TABLE entry_comment DROP ap_share_count');
$this->addSql('ALTER TABLE post_comment DROP ap_like_count');
$this->addSql('ALTER TABLE post_comment DROP ap_dislike_count');
$this->addSql('ALTER TABLE post_comment DROP ap_share_count');
$this->addSql('ALTER TABLE post DROP ap_like_count');
$this->addSql('ALTER TABLE post DROP ap_dislike_count');
$this->addSql('ALTER TABLE post DROP ap_share_count');
$this->addSql('ALTER TABLE entry DROP ap_like_count');
$this->addSql('ALTER TABLE entry DROP ap_dislike_count');
$this->addSql('ALTER TABLE entry DROP ap_share_count');
}
}
3 changes: 3 additions & 0 deletions src/DTO/EntryCommentDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class EntryCommentDto
public ?string $visibility = VisibilityInterface::VISIBILITY_VISIBLE;
public ?string $ip = null;
public ?string $apId = null;
public ?int $apLikeCount = null;
public ?int $apDislikeCount = null;
public ?int $apShareCount = null;
public ?array $mentions = null;
public ?\DateTimeImmutable $createdAt = null;
public ?\DateTimeImmutable $editedAt = null;
Expand Down
3 changes: 3 additions & 0 deletions src/DTO/EntryDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class EntryDto implements ContentVisibilityInterface
public ?string $visibility = VisibilityInterface::VISIBILITY_VISIBLE;
public ?string $ip = null;
public ?string $apId = null;
public ?int $apLikeCount = null;
public ?int $apDislikeCount = null;
public ?int $apShareCount = null;
public ?array $tags = null;
public ?\DateTimeImmutable $createdAt = null;
public ?\DateTimeImmutable $editedAt = null;
Expand Down
3 changes: 3 additions & 0 deletions src/DTO/PostCommentDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class PostCommentDto implements ContentVisibilityInterface
public ?string $visibility = VisibilityInterface::VISIBILITY_VISIBLE;
public ?string $ip = null;
public ?string $apId = null;
public ?int $apLikeCount = null;
public ?int $apDislikeCount = null;
public ?int $apShareCount = null;
public ?array $mentions = null;
public ?\DateTimeImmutable $createdAt = null;
public ?\DateTimeImmutable $editedAt = null;
Expand Down
3 changes: 3 additions & 0 deletions src/DTO/PostDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class PostDto implements ContentVisibilityInterface
public ?string $ip = null;
public ?array $mentions = null;
public ?string $apId = null;
public ?int $apLikeCount = null;
public ?int $apDislikeCount = null;
public ?int $apShareCount = null;
public ?\DateTimeImmutable $createdAt = null;
public ?\DateTimeImmutable $editedAt = null;
public ?\DateTime $lastActive = null;
Expand Down
2 changes: 1 addition & 1 deletion src/Entity/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public function addVote(Vote $vote): self

public function updateScore(): self
{
$this->score = $this->getUpVotes()->count() + $this->favouriteCount - $this->getDownVotes()->count();
$this->score = ($this->apShareCount ?? $this->getUpVotes()->count()) + ($this->apLikeCount ?? $this->favouriteCount) - ($this->apDislikeCount ?? $this->getDownVotes()->count());

return $this;
}
Expand Down
16 changes: 13 additions & 3 deletions src/Entity/Traits/VotableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Column;

trait VotableTrait
{
Expand All @@ -19,19 +20,28 @@ trait VotableTrait
#[ORM\Column(type: 'integer')]
private int $downVotes = 0;

#[Column(type: 'integer', nullable: true)]
public ?int $apLikeCount = null;

#[Column(type: 'integer', nullable: true)]
public ?int $apDislikeCount = null;

#[Column(type: 'integer', nullable: true)]
public ?int $apShareCount = null;

public function countUpVotes(): int
{
return $this->upVotes;
return $this->apShareCount ?? $this->upVotes;
}

public function countDownVotes(): int
{
return $this->downVotes;
return $this->apDislikeCount ?? $this->downVotes;
}

public function countVotes(): int
{
return $this->downVotes + $this->upVotes;
return $this->countDownVotes() + $this->countUpVotes();
}

public function getUserChoice(User $user): int
Expand Down
4 changes: 4 additions & 0 deletions src/Factory/EntryCommentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ public function createDto(EntryComment $comment): EntryCommentDto
$dto->createdAt = $comment->createdAt;
$dto->editedAt = $comment->editedAt;
$dto->lastActive = $comment->lastActive;
$dto->apId = $comment->apId;
$dto->apLikeCount = $comment->apLikeCount;
$dto->apDislikeCount = $comment->apDislikeCount;
$dto->apShareCount = $comment->apShareCount;
$dto->setId($comment->getId());

$currentUser = $this->security->getUser();
Expand Down
3 changes: 3 additions & 0 deletions src/Factory/EntryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public function createDto(Entry $entry): EntryDto
$dto->isPinned = $entry->sticky;
$dto->type = $entry->type;
$dto->apId = $entry->apId;
$dto->apLikeCount = $entry->apLikeCount;
$dto->apDislikeCount = $entry->apDislikeCount;
$dto->apShareCount = $entry->apShareCount;
$dto->tags = $this->tagLinkRepository->getTagsOfEntry($entry);

$currentUser = $this->security->getUser();
Expand Down
4 changes: 4 additions & 0 deletions src/Factory/PostCommentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ public function createDto(PostComment $comment): PostCommentDto
$dto->setId($comment->getId());
$dto->parent = $comment->parent;
$dto->mentions = $comment->mentions;
$dto->apId = $comment->apId;
$dto->apLikeCount = $comment->apLikeCount;
$dto->apDislikeCount = $comment->apDislikeCount;
$dto->apShareCount = $comment->apShareCount;

$currentUser = $this->security->getUser();
// Only return the user's vote if permission to control voting has been given
Expand Down
3 changes: 3 additions & 0 deletions src/Factory/PostFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public function createDto(Post $post): PostDto
$dto->ip = $post->ip;
$dto->mentions = $post->mentions;
$dto->apId = $post->apId;
$dto->apLikeCount = $post->apLikeCount;
$dto->apDislikeCount = $post->apDislikeCount;
$dto->apShareCount = $post->apShareCount;
$dto->setId($post->getId());

$currentUser = $this->security->getUser();
Expand Down
5 changes: 3 additions & 2 deletions src/MessageHandler/ActivityPub/Inbox/ActivityHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ public function __invoke(ActivityMessage $message): void

try {
if (isset($payload['actor']) || isset($payload['attributedTo'])) {
if (!$this->verifyInstanceDomain($payload['actor'] ?? $payload['attributedTo'])) {
if (!$this->verifyInstanceDomain($payload['actor'] ?? $this->manager->getActorFromAttributedTo($payload['attributedTo']))) {
return;
}
$user = $this->manager->findActorOrCreate($payload['actor'] ?? $payload['attributedTo']);
$user = $this->manager->findActorOrCreate($payload['actor'] ?? $this->manager->getActorFromAttributedTo($payload['attributedTo']));
} else {
if (!$this->verifyInstanceDomain($payload['id'])) {
return;
Expand Down Expand Up @@ -139,6 +139,7 @@ private function handle(?array $payload)
case 'Page':
case 'Article':
case 'Question':
case 'Video':
$this->bus->dispatch(new CreateMessage($payload));
// no break
case 'Announce':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function __invoke(ChainActivityMessage $message): void
if (!$message->chain || 0 === \sizeof($message->chain)) {
return;
}
$validObjectTypes = ['Page', 'Note', 'Article', 'Question'];
$validObjectTypes = ['Page', 'Note', 'Article', 'Question', 'Video'];
$object = $message->chain[0];
if (!\in_array($object['type'], $validObjectTypes)) {
$this->logger->error('cannot get the dependencies of the object, its type {t} is not one we can handle. {m]', ['t' => $object['type'], 'm' => $message]);
Expand Down Expand Up @@ -107,6 +107,7 @@ private function retrieveObject(string $apUrl): Entry|EntryComment|Post|PostComm
return $this->note->create($object);
case 'Page':
case 'Article':
case 'Video':
$this->logger->debug('creating page {o}', ['o' => $object]);

return $this->page->create($object);
Expand Down
14 changes: 4 additions & 10 deletions src/MessageHandler/ActivityPub/Inbox/CreateHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,17 @@ public function __invoke(CreateMessage $message): void
{
$this->object = $message->payload;
$this->logger->debug('Got a CreateMessage of type {t}', [$message->payload['type'], $message->payload]);
$entryTypes = ['Page', 'Article', 'Video'];
$postTypes = ['Question', 'Note'];

try {
if ('Note' === $this->object['type']) {
if (\in_array($this->object['type'], $postTypes)) {
$this->handleChain();
}

if ('Page' === $this->object['type']) {
if (\in_array($this->object['type'], $entryTypes)) {
$this->handlePage();
}

if ('Article' === $this->object['type']) {
$this->handlePage();
}

if ('Question' === $this->object['type']) {
$this->handleChain();
}
} catch (UserBannedException) {
$this->logger->info('Did not create the post, because the user is banned');
} catch (TagBannedException) {
Expand Down
59 changes: 25 additions & 34 deletions src/MessageHandler/ActivityPub/Inbox/UpdateHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace App\MessageHandler\ActivityPub\Inbox;

use App\DTO\EntryCommentDto;
use App\DTO\EntryDto;
use App\DTO\PostCommentDto;
use App\DTO\PostDto;
use App\Entity\Entry;
use App\Entity\EntryComment;
use App\Entity\Post;
Expand All @@ -16,15 +20,13 @@
use App\Message\ActivityPub\Inbox\UpdateMessage;
use App\Repository\ApActivityRepository;
use App\Service\ActivityPub\ApObjectExtractor;
use App\Service\ActivityPub\MarkdownConverter;
use App\Service\ActivityPubManager;
use App\Service\EntryCommentManager;
use App\Service\EntryManager;
use App\Service\PostCommentManager;
use App\Service\PostManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface;

#[AsMessageHandler]
class UpdateHandler
Expand All @@ -39,12 +41,10 @@ public function __construct(
private readonly EntryCommentManager $entryCommentManager,
private readonly PostManager $postManager,
private readonly PostCommentManager $postCommentManager,
private readonly MarkdownConverter $markdownConverter,
private readonly EntryFactory $entryFactory,
private readonly EntryCommentFactory $entryCommentFactory,
private readonly PostFactory $postFactory,
private readonly PostCommentFactory $postCommentFactory,
private readonly MessageBusInterface $bus,
private readonly ApObjectExtractor $objectExtractor,
) {
}
Expand All @@ -68,23 +68,19 @@ public function __invoke(UpdateMessage $message): void
$object = $this->entityManager->getRepository($object['type'])->find((int) $object['id']);

if (Entry::class === \get_class($object)) {
$fn = 'editEntry';
$this->editEntry($object, $actor);
}

if (EntryComment::class === \get_class($object)) {
$fn = 'editEntryComment';
$this->editEntryComment($object, $actor);
}

if (Post::class === \get_class($object)) {
$fn = 'editPost';
$this->editPost($object, $actor);
}

if (PostComment::class === \get_class($object)) {
$fn = 'editPostComment';
}

if (isset($fn, $object, $actor)) {
$this->$fn($object, $actor);
$this->editPostComment($object, $actor);
}

// Dead-code introduced by Ernest "Temp disable handler dispatch", in commit:
Expand All @@ -101,57 +97,52 @@ public function __invoke(UpdateMessage $message): void
// }
}

private function editEntry(Entry $entry, User $user)
private function editEntry(Entry $entry, User $user): void
{
$dto = $this->entryFactory->createDto($entry);

$dto->title = $this->payload['object']['name'];

if (!empty($this->payload['object']['content'])) {
$dto->body = $this->objectExtractor->getMarkdownBody($this->payload['object']);
} else {
$dto->body = null;
}

$this->extractChanges($dto);
$this->entryManager->edit($entry, $dto);
}

private function editEntryComment(EntryComment $comment, User $user)
private function editEntryComment(EntryComment $comment, User $user): void
{
$dto = $this->entryCommentFactory->createDto($comment);

if (!empty($this->payload['object']['content'])) {
$dto->body = $this->objectExtractor->getMarkdownBody($this->payload['object']);
} else {
$dto->body = null;
}
$this->extractChanges($dto);

$this->entryCommentManager->edit($comment, $dto);
}

private function editPost(Post $post, User $user)
private function editPost(Post $post, User $user): void
{
$dto = $this->postFactory->createDto($post);

if (!empty($this->payload['object']['content'])) {
$dto->body = $this->objectExtractor->getMarkdownBody($this->payload['object']);
} else {
$dto->body = null;
}
$this->extractChanges($dto);

$this->postManager->edit($post, $dto);
}

private function editPostComment(PostComment $comment, User $user)
private function editPostComment(PostComment $comment, User $user): void
{
$dto = $this->postCommentFactory->createDto($comment);

$this->extractChanges($dto);

$this->postCommentManager->edit($comment, $dto);
}

private function extractChanges(EntryDto|EntryCommentDto|PostDto|PostCommentDto $dto): void
{
if (!empty($this->payload['object']['content'])) {
$dto->body = $this->objectExtractor->getMarkdownBody($this->payload['object']);
} else {
$dto->body = null;
}

$this->postCommentManager->edit($comment, $dto);
$dto->apLikeCount = $this->activityPubManager->extractRemoteLikeCount($this->payload['object']);
$dto->apDislikeCount = $this->activityPubManager->extractRemoteDislikeCount($this->payload['object']);
$dto->apShareCount = $this->activityPubManager->extractRemoteShareCount($this->payload['object']);
}
}
2 changes: 1 addition & 1 deletion src/Service/ActivityPub/ApHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ function (ItemInterface $item) use ($apProfileId) {
/**
* @throws InvalidArgumentException
*/
public function getCollectionObject(string $apAddress)
public function getCollectionObject(string $apAddress): ?array
{
$resp = $this->cache->get(
'ap_collection'.hash('sha256', $apAddress),
Expand Down
Loading

0 comments on commit 4e43b06

Please sign in to comment.