154 lines
5 KiB
PHP
154 lines
5 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Lemmy\Services;
|
|
|
|
use App\Enums\PlatformEnum;
|
|
use App\Exceptions\PlatformAuthException;
|
|
use App\Exceptions\PublishException;
|
|
use App\Models\Article;
|
|
use App\Models\ArticlePublication;
|
|
use App\Models\PlatformAccount;
|
|
use App\Services\Auth\LemmyAuthService;
|
|
use Exception;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use RuntimeException;
|
|
|
|
class LemmyPublisher
|
|
{
|
|
private LemmyApiService $api;
|
|
private PlatformAccount $account;
|
|
|
|
public function __construct(PlatformAccount $account)
|
|
{
|
|
$this->api = new LemmyApiService($account->instance_url);
|
|
$this->account = $account;
|
|
}
|
|
|
|
public static function fromActiveAccount(): self
|
|
{
|
|
$accounts = PlatformAccount::getActive(PlatformEnum::LEMMY);
|
|
|
|
if ($accounts->isEmpty()) {
|
|
throw new RuntimeException('No active Lemmy accounts configured'); // TODO Also make this into a PublishException
|
|
}
|
|
|
|
return new self($accounts->first());
|
|
}
|
|
|
|
/**
|
|
* @throws PublishException
|
|
*/
|
|
public function publish(Article $article, array $extractedData): Collection
|
|
{
|
|
$publications = collect();
|
|
$activeCommunities = $this->account->activeCommunities;
|
|
|
|
if ($activeCommunities->isEmpty()) {
|
|
throw new PublishException($article, PlatformEnum::LEMMY, new RuntimeException('No active communities configured for account: ' . $this->account->username));
|
|
}
|
|
|
|
$activeCommunities->each(function ($community) use ($article, $extractedData, $publications) {
|
|
try {
|
|
$publication = $this->publishToCommunity($article, $extractedData, $community);
|
|
$publications->push($publication);
|
|
} catch (Exception $e) {
|
|
logger()->warning('Failed to publish to community', [
|
|
'article_id' => $article->id,
|
|
'community' => $community->name,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|
|
});
|
|
|
|
if ($publications->isEmpty()) {
|
|
throw new PublishException($article, PlatformEnum::LEMMY, new RuntimeException('Failed to publish to any community'));
|
|
}
|
|
|
|
return $publications;
|
|
}
|
|
|
|
/**
|
|
* @throws PlatformAuthException
|
|
* @throws Exception
|
|
*/
|
|
private function publishToCommunity(Article $article, array $extractedData, $community): ArticlePublication
|
|
{
|
|
$token = LemmyAuthService::getToken($this->account);
|
|
$languageId = $this->getLanguageIdForSource($article->url);
|
|
|
|
$postData = $this->api->createPost(
|
|
$token,
|
|
$extractedData['title'] ?? 'Untitled',
|
|
$extractedData['description'] ?? '',
|
|
(int) $community->community_id,
|
|
$article->url,
|
|
$extractedData['thumbnail'] ?? null,
|
|
$languageId
|
|
);
|
|
|
|
return $this->createPublicationRecord($article, $postData, (int) $community->community_id);
|
|
}
|
|
|
|
private function createPublicationRecord(Article $article, array $postData, int $communityId): ArticlePublication
|
|
{
|
|
return ArticlePublication::create([
|
|
'article_id' => $article->id,
|
|
'post_id' => $postData['post_view']['post']['id'],
|
|
'community_id' => $communityId,
|
|
'published_by' => $this->account->username,
|
|
'published_at' => now(),
|
|
'platform' => 'lemmy',
|
|
'publication_data' => $postData,
|
|
]);
|
|
}
|
|
|
|
private function getLanguageIdForSource(string $url): ?int
|
|
{
|
|
// TODO this will be obsolete when sources can be created from the UI, so we can remove these hard-coded sources
|
|
|
|
// VRT articles are in Dutch
|
|
if (str_contains($url, 'vrt.be')) {
|
|
return $this->getLanguageId('nl'); // Dutch
|
|
}
|
|
|
|
// Belga articles are in English (based on URL structure)
|
|
if (str_contains($url, 'belganewsagency.eu')) {
|
|
return $this->getLanguageId('en'); // English
|
|
}
|
|
|
|
return null; // Default to no language specified
|
|
}
|
|
|
|
private function getLanguageId(string $languageCode): ?int
|
|
{
|
|
$cacheKey = "lemmy_language_id_$languageCode";
|
|
$cachedId = Cache::get($cacheKey);
|
|
|
|
if ($cachedId !== null) {
|
|
return $cachedId;
|
|
}
|
|
|
|
try {
|
|
$languages = $this->api->getLanguages();
|
|
|
|
foreach ($languages as $language) {
|
|
if (isset($language['code']) && $language['code'] === $languageCode) {
|
|
$languageId = $language['id'];
|
|
Cache::put($cacheKey, $languageId, 3600);
|
|
return $languageId;
|
|
}
|
|
}
|
|
|
|
// Cache null result to avoid repeated API calls
|
|
Cache::put($cacheKey, null, 3600);
|
|
return null;
|
|
} catch (Exception $e) {
|
|
logger()->warning('Failed to get language ID', [
|
|
'language_code' => $languageCode,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
}
|