fedi-feed-router/app/Modules/Lemmy/Services/LemmyPublisher.php

101 lines
3.2 KiB
PHP
Raw Permalink Normal View History

2025-06-29 21:20:45 +02:00
<?php
namespace App\Modules\Lemmy\Services;
2025-07-05 02:19:59 +02:00
use App\Exceptions\PlatformAuthException;
2025-06-29 21:20:45 +02:00
use App\Models\Article;
2025-07-05 01:55:53 +02:00
use App\Models\PlatformAccount;
2025-07-05 18:26:04 +02:00
use App\Models\PlatformChannel;
2025-07-02 21:32:37 +02:00
use App\Services\Auth\LemmyAuthService;
use App\Services\Log\LogSaver;
2025-06-29 21:20:45 +02:00
use Exception;
class LemmyPublisher
{
private LemmyApiService $api;
2025-07-05 01:55:53 +02:00
private PlatformAccount $account;
2025-06-29 21:20:45 +02:00
private ThumbnailUploader $thumbnailUploader;
2025-07-05 01:55:53 +02:00
public function __construct(PlatformAccount $account)
2025-06-29 21:20:45 +02:00
{
2025-07-05 01:55:53 +02:00
$this->api = new LemmyApiService($account->instance_url);
$this->account = $account;
$this->thumbnailUploader = new ThumbnailUploader($account->instance_url);
2025-06-29 21:20:45 +02:00
}
2025-07-05 01:55:53 +02:00
/**
* @param array<string, mixed> $extractedData
2025-07-07 00:51:32 +02:00
* @return array<string, mixed>
*
2025-07-05 02:19:59 +02:00
* @throws PlatformAuthException
2025-07-05 01:55:53 +02:00
* @throws Exception
*/
2025-07-05 18:26:04 +02:00
public function publishToChannel(Article $article, array $extractedData, PlatformChannel $channel): array
2025-06-29 21:20:45 +02:00
{
$authService = resolve(LemmyAuthService::class);
$token = $authService->getToken($this->account);
2025-07-05 02:19:59 +02:00
$thumbnail = $this->hostedThumbnail($extractedData, $channel, $article, $token);
try {
return $this->createPost($token, $extractedData, $channel, $article, $thumbnail);
} catch (Exception $e) {
// If the cached token was stale, refresh and retry once
if (str_contains($e->getMessage(), 'not_logged_in') || str_contains($e->getMessage(), 'Unauthorized')) {
$token = $authService->refreshToken($this->account);
return $this->createPost($token, $extractedData, $channel, $article, $thumbnail);
}
throw $e;
}
}
/**
* Uploaded once per publish, outside the stale-token retry: the upload is the expensive
* part and a retry would otherwise re-download, re-encode and re-log.
*
* @param array<string, mixed> $extractedData
*/
private function hostedThumbnail(array $extractedData, PlatformChannel $channel, Article $article, string $token): ?string
{
$source = $extractedData['thumbnail'] ?? null;
$source = is_string($source) && $source !== '' ? $source : null;
2025-07-05 18:26:04 +02:00
if ($source === null) {
return null;
}
$hosted = $this->thumbnailUploader->upload($source, $token);
if ($hosted === null) {
app(LogSaver::class)->warning('Thumbnail upload failed; publishing without one', $channel, [
'article_id' => $article->id,
'source' => $source,
]);
}
return $hosted;
}
/**
* @param array<string, mixed> $extractedData
* @return array<string, mixed>
*/
private function createPost(string $token, array $extractedData, PlatformChannel $channel, Article $article, ?string $thumbnail = null): array
{
$languageId = $extractedData['language_id'] ?? null;
2025-07-05 18:26:04 +02:00
return $this->api->createPost(
2025-07-05 02:19:59 +02:00
$token,
$extractedData['title'] ?? 'Untitled',
$extractedData['description'] ?? '',
$channel->channel_id,
2025-07-05 02:19:59 +02:00
$article->url,
$thumbnail,
2025-07-05 02:19:59 +02:00
$languageId
);
2025-06-29 21:20:45 +02:00
}
2025-06-30 18:18:30 +02:00
}