fedi-feed-router/backend/app/Jobs/SyncChannelPostsJob.php

112 lines
3.5 KiB
PHP

<?php
namespace App\Jobs;
use App\Enums\PlatformEnum;
use App\Exceptions\PlatformAuthException;
use App\Models\PlatformAccount;
use App\Models\PlatformChannel;
use App\Modules\Lemmy\Services\LemmyApiService;
use App\Services\Log\LogSaver;
use Exception;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Cache;
class SyncChannelPostsJob implements ShouldQueue, ShouldBeUnique
{
use Queueable;
public function __construct(
private readonly PlatformChannel $channel
) {
$this->onQueue('sync');
}
public static function dispatchForAllActiveChannels(): void
{
PlatformChannel::with(['platformInstance', 'platformAccounts'])
->whereHas('platformInstance', fn ($query) => $query->where('platform', PlatformEnum::LEMMY))
->whereHas('platformAccounts', fn ($query) => $query->where('platform_accounts.is_active', true))
->where('platform_channels.is_active', true)
->get()
->each(function (PlatformChannel $channel) {
self::dispatch($channel);
LogSaver::info('Dispatched sync job for channel', $channel);
});
}
public function handle(): void
{
LogSaver::info('Starting channel posts sync job', $this->channel);
match ($this->channel->platformInstance->platform) {
PlatformEnum::LEMMY => $this->syncLemmyChannelPosts(),
};
LogSaver::info('Channel posts sync job completed', $this->channel);
}
/**
* @throws PlatformAuthException
*/
private function syncLemmyChannelPosts(): void
{
try {
/** @var Collection<int, PlatformAccount> $accounts */
$accounts = $this->channel->activePlatformAccounts()->get();
$account = $accounts->first();
if (! $account) {
throw new PlatformAuthException(PlatformEnum::LEMMY, 'No active account found for channel');
}
$api = new LemmyApiService($this->channel->platformInstance->url);
$token = $this->getAuthToken($api, $account);
$platformChannelId = $this->channel->channel_id
? $this->channel->channel_id
: $api->getCommunityId($this->channel->name, $token);
$api->syncChannelPosts($token, $platformChannelId, $this->channel->name);
LogSaver::info('Channel posts synced successfully', $this->channel);
} catch (Exception $e) {
LogSaver::error('Failed to sync channel posts', $this->channel, [
'error' => $e->getMessage()
]);
throw $e;
}
}
/**
* @throws PlatformAuthException
*/
private function getAuthToken(LemmyApiService $api, PlatformAccount $account): string
{
$cacheKey = "lemmy_jwt_token_{$account->id}";
$cachedToken = Cache::get($cacheKey);
if ($cachedToken) {
return $cachedToken;
}
if (!$account->username || !$account->password) {
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Missing credentials for account');
}
$token = $api->login($account->username, $account->password);
if (!$token) {
throw new PlatformAuthException(PlatformEnum::LEMMY, 'Login failed for account');
}
Cache::put($cacheKey, $token, 3600);
return $token;
}
}