From 9dc3272d40a1734b5617b6dd7c8e1cede703ed47 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 27 Jul 2023 18:28:25 +0200 Subject: [PATCH] [wip] mastodon integration --- .env | 4 ++ composer.json | 1 + config/services.yaml | 11 ++++ src/Api/MastodonClient.php | 60 +++++++++++++++++++ src/Command/MastodonCommentsSyncCommand.php | 49 +++++++++++++++ src/Entity/Blog/Post.php | 30 ++++++++++ src/Entity/ExportQueue.php | 20 +++++++ src/Form/Blog/PostType.php | 13 ++++ src/Repository/ExportQueueRepository.php | 66 +++++++++++++++++++++ templates/blog/post_admin/_form.html.twig | 2 +- templates/blog/post_admin/_show.html.twig | 5 ++ 11 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 src/Api/MastodonClient.php create mode 100644 src/Command/MastodonCommentsSyncCommand.php create mode 100644 src/Entity/ExportQueue.php create mode 100644 src/Repository/ExportQueueRepository.php diff --git a/.env b/.env index 5b6040b..15ff816 100644 --- a/.env +++ b/.env @@ -35,3 +35,7 @@ MAILER_SENDER=example@localhost ASSET_BASE_URL=null UMAMI_URL=null +MASTODON_HOST= +MASTODON_CLIENT_ID= +MASTODON_CLIENT_SECRET= +MASTODON_CLIENT_ACCESS_TOKEN= diff --git a/composer.json b/composer.json index 6ac589f..794e5b8 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "php": ">=8.0.0", "beberlei/doctrineextensions": "^1.3", "friendsofsymfony/jsrouting-bundle": "^2.7", + "fundevogel/php-mastodon": "^0.6.0", "gregwar/captcha-bundle": "^2.2", "knplabs/knp-markdown-bundle": "^1.9", "knplabs/knp-menu-bundle": "^3.1", diff --git a/config/services.yaml b/config/services.yaml index 832f63b..2ff4933 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,6 +4,10 @@ # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration parameters: + mastodon_host: '%env(MASTODON_HOST)%' + mastodon_client_id: '%env(MASTODON_CLIENT_ID)%' + mastodon_client_secret: '%env(MASTODON_CLIENT_SECRET)%' + mastodon_client_access_token: '%env(MASTODON_CLIENT_ACCESS_TOKEN)%' services: # default configuration for services in *this* file @@ -47,6 +51,13 @@ services: resource: '../src/Controller/' tags: ['controller.service_arguments'] + App\Api\MastodonClient: + arguments: + $host: '%mastodon_host%' + $clientId: '%mastodon_client_id%' + $clientSecret: '%mastodon_client_secret%' + $clientAccessToken: '%mastodon_client_access_token%' + site.route_loader: class: App\Core\Router\SiteRouteLoader tags: [routing.loader] diff --git a/src/Api/MastodonClient.php b/src/Api/MastodonClient.php new file mode 100644 index 0000000..4ee07d8 --- /dev/null +++ b/src/Api/MastodonClient.php @@ -0,0 +1,60 @@ + + */ +class MastodonClient +{ + protected ?Client $client = null; + + public function __construct( + protected ?string $host, + protected ?string $clientId, + protected ?string $clientSecret, + protected ?string $clientAccessToken + ) { + } + + public function __call(string $name, array $arguments) + { + if (!$this->client) { + $this->createClient(); + } + + return call_user_func_array([$this->client, $name], $arguments); + } + + protected function createClient(): self + { + $this->client = new Client($this->host); + $this->client->accessToken = $this->clientAccessToken; + + return $this; + } + + public function extractId(string $url): string + { + return basename($url); + } + + public function getTree(string $postId, array &$tree = []): array + { + $tree['id'] = $postId; + $tree = array_merge($tree, $this->statuses()->get($postId)->data); + $tree = array_merge($tree, $this->statuses()->context($postId)->data); + + foreach ($tree['descendants'] as $key => $descendant) { + if ($descendant['in_reply_to_id'] === $postId) { + $descendants['descendants'][$key] = $this->getTree($descendant['id'], $descendants['descendants'][$key]); + } + } + + return $tree; + } +} diff --git a/src/Command/MastodonCommentsSyncCommand.php b/src/Command/MastodonCommentsSyncCommand.php new file mode 100644 index 0000000..ee5b0d4 --- /dev/null +++ b/src/Command/MastodonCommentsSyncCommand.php @@ -0,0 +1,49 @@ +addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') + // ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') + // ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + foreach ($this->query->create()->where('.mastodonUrl is not null')->find() as $post) { + dump($this->client->getTree($this->client->extractId($post->getMastodonUrl()))); + } + + return Command::SUCCESS; + } +} diff --git a/src/Entity/Blog/Post.php b/src/Entity/Blog/Post.php index 505c4e4..8d6d1d5 100644 --- a/src/Entity/Blog/Post.php +++ b/src/Entity/Blog/Post.php @@ -90,6 +90,12 @@ class Post implements EntityInterface #[ORM\Column(type: 'array')] private $parameters = []; + #[ORM\Column(type: 'string', length: 255, nullable: true)] + private $mastodonUrl; + + #[ORM\Column(type: 'json')] + private $mastodonComments = []; + public function __construct() { $this->categories = new ArrayCollection(); @@ -475,4 +481,28 @@ class Post implements EntityInterface } )[0]['value'] ?? null; } + + public function getMastodonUrl(): ?string + { + return $this->mastodonUrl; + } + + public function setMastodonUrl(?string $mastodonUrl): self + { + $this->mastodonUrl = $mastodonUrl; + + return $this; + } + + public function getMastodonComments(): ?array + { + return $this->mastodonComments; + } + + public function setMastodonComments(array $mastodonComments): self + { + $this->mastodonComments = $mastodonComments; + + return $this; + } } diff --git a/src/Entity/ExportQueue.php b/src/Entity/ExportQueue.php new file mode 100644 index 0000000..efbd0d4 --- /dev/null +++ b/src/Entity/ExportQueue.php @@ -0,0 +1,20 @@ +id; + } +} diff --git a/src/Form/Blog/PostType.php b/src/Form/Blog/PostType.php index 5661886..f38bbd4 100644 --- a/src/Form/Blog/PostType.php +++ b/src/Form/Blog/PostType.php @@ -202,6 +202,19 @@ class PostType extends AbstractType ] ); + $builder->add( + 'mastodonUrl', + TextType::class, + [ + 'label' => 'URL Mastodon', + 'required' => false, + 'attr' => [ + ], + 'constraints' => [ + ], + ] + ); + $builder->add( 'quickUrl', TextType::class, diff --git a/src/Repository/ExportQueueRepository.php b/src/Repository/ExportQueueRepository.php new file mode 100644 index 0000000..4ef538d --- /dev/null +++ b/src/Repository/ExportQueueRepository.php @@ -0,0 +1,66 @@ + + * + * @method ExportQueue|null find($id, $lockMode = null, $lockVersion = null) + * @method ExportQueue|null findOneBy(array $criteria, array $orderBy = null) + * @method ExportQueue[] findAll() + * @method ExportQueue[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ExportQueueRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ExportQueue::class); + } + + public function add(ExportQueue $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ExportQueue $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return ExportQueue[] Returns an array of ExportQueue objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('e') +// ->andWhere('e.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('e.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?ExportQueue +// { +// return $this->createQueryBuilder('e') +// ->andWhere('e.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/templates/blog/post_admin/_form.html.twig b/templates/blog/post_admin/_form.html.twig index 2983cd8..eadd08a 100644 --- a/templates/blog/post_admin/_form.html.twig +++ b/templates/blog/post_admin/_form.html.twig @@ -38,7 +38,7 @@ - {% for item in ['image', 'image2', 'parameters', 'status', 'contentFormat', 'publishedAt'] %} + {% for item in ['image', 'image2', 'parameters', 'status', 'contentFormat', 'publishedAt', 'mastodonUrl'] %}
{{ form_row(form[item]) }}
diff --git a/templates/blog/post_admin/_show.html.twig b/templates/blog/post_admin/_show.html.twig index f3dae48..fee41e7 100644 --- a/templates/blog/post_admin/_show.html.twig +++ b/templates/blog/post_admin/_show.html.twig @@ -125,6 +125,11 @@ {{ entity.publishedAt ? entity.publishedAt|date('d/m/Y H:i') : '-' }} +
  • + URL Mastodon + + {{ entity.mastodonUrl|default('-') }} +