fix: review #5 — ContentSanitizer in all publishers, refresh lock, CheckSocialConnections includes TokenExpired
This commit is contained in:
parent
a69dc28298
commit
a1df51234b
6 changed files with 50 additions and 31 deletions
|
|
@ -19,7 +19,7 @@ public function handle(): void
|
|||
{
|
||||
Workspace::query()
|
||||
->whereHas('socialAccounts', function ($query) {
|
||||
$query->where('status', Status::Connected);
|
||||
$query->whereIn('status', [Status::Connected, Status::TokenExpired]);
|
||||
})
|
||||
->with('owner')
|
||||
->chunk(100, function ($workspaces) {
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ public function markAsTokenExpired(string $errorMessage): void
|
|||
$this->update([
|
||||
'status' => Status::TokenExpired,
|
||||
'error_message' => $errorMessage,
|
||||
'disconnected_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
use App\Enums\SocialAccount\Platform;
|
||||
use App\Exceptions\TokenExpiredException;
|
||||
use App\Models\SocialAccount;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
|
@ -46,19 +47,32 @@ public function verify(SocialAccount $account): bool
|
|||
*/
|
||||
private function refreshTokenIfNeeded(SocialAccount $account): void
|
||||
{
|
||||
match ($account->platform) {
|
||||
Platform::LinkedIn, Platform::LinkedInPage => $this->refreshLinkedInToken($account),
|
||||
Platform::X => $this->refreshXToken($account),
|
||||
Platform::Bluesky => $this->refreshBlueskyToken($account),
|
||||
Platform::YouTube => $this->refreshYouTubeToken($account),
|
||||
Platform::TikTok => $this->refreshTikTokToken($account),
|
||||
Platform::Pinterest => $this->refreshPinterestToken($account),
|
||||
Platform::Threads => $this->refreshThreadsToken($account),
|
||||
Platform::Instagram => $this->refreshInstagramToken($account),
|
||||
// Facebook uses page tokens that don't expire
|
||||
// Mastodon tokens don't expire
|
||||
default => null,
|
||||
};
|
||||
$lock = Cache::lock("token_refresh:{$account->id}", 30);
|
||||
|
||||
if (! $lock->get()) {
|
||||
// Another process is already refreshing this token
|
||||
$account->refresh();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
match ($account->platform) {
|
||||
Platform::LinkedIn, Platform::LinkedInPage => $this->refreshLinkedInToken($account),
|
||||
Platform::X => $this->refreshXToken($account),
|
||||
Platform::Bluesky => $this->refreshBlueskyToken($account),
|
||||
Platform::YouTube => $this->refreshYouTubeToken($account),
|
||||
Platform::TikTok => $this->refreshTikTokToken($account),
|
||||
Platform::Pinterest => $this->refreshPinterestToken($account),
|
||||
Platform::Threads => $this->refreshThreadsToken($account),
|
||||
Platform::Instagram => $this->refreshInstagramToken($account),
|
||||
// Facebook uses page tokens that don't expire
|
||||
// Mastodon tokens don't expire
|
||||
default => null,
|
||||
};
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
|
||||
private function refreshLinkedInToken(SocialAccount $account): void
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ public function publish(PostPlatform $postPlatform): array
|
|||
{
|
||||
$this->validateContentLength($postPlatform);
|
||||
|
||||
$content = $postPlatform->content ? app(ContentSanitizer::class)->sanitize($postPlatform->content, $postPlatform->platform) : null;
|
||||
|
||||
$account = $postPlatform->socialAccount;
|
||||
$instance = $account->meta['instance'] ?? 'https://mastodon.social';
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ public function publish(PostPlatform $postPlatform): array
|
|||
|
||||
// Create status
|
||||
$payload = [
|
||||
'status' => $postPlatform->content ?? '',
|
||||
'status' => $content ?? '',
|
||||
'visibility' => 'public',
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -32,15 +32,17 @@ public function publish(PostPlatform $postPlatform): array
|
|||
$account->refresh();
|
||||
}
|
||||
|
||||
$content = $postPlatform->content ? app(ContentSanitizer::class)->sanitize($postPlatform->content, $postPlatform->platform) : null;
|
||||
|
||||
return match ($postPlatform->content_type) {
|
||||
ContentType::PinterestPin => $this->publishImagePin($postPlatform),
|
||||
ContentType::PinterestVideoPin => $this->publishVideoPin($postPlatform),
|
||||
ContentType::PinterestCarousel => $this->publishCarousel($postPlatform),
|
||||
ContentType::PinterestPin => $this->publishImagePin($postPlatform, $content),
|
||||
ContentType::PinterestVideoPin => $this->publishVideoPin($postPlatform, $content),
|
||||
ContentType::PinterestCarousel => $this->publishCarousel($postPlatform, $content),
|
||||
default => throw new \Exception("Unsupported content type: {$postPlatform->content_type->value}"),
|
||||
};
|
||||
}
|
||||
|
||||
private function publishImagePin(PostPlatform $postPlatform): array
|
||||
private function publishImagePin(PostPlatform $postPlatform, ?string $content): array
|
||||
{
|
||||
$account = $postPlatform->socialAccount;
|
||||
$media = $postPlatform->media->first();
|
||||
|
|
@ -87,8 +89,8 @@ private function publishImagePin(PostPlatform $postPlatform): array
|
|||
],
|
||||
];
|
||||
|
||||
if ($postPlatform->content) {
|
||||
$payload['description'] = $postPlatform->content;
|
||||
if ($content) {
|
||||
$payload['description'] = $content;
|
||||
}
|
||||
|
||||
if (! empty(data_get($postPlatform->meta, 'title'))) {
|
||||
|
|
@ -122,7 +124,7 @@ private function publishImagePin(PostPlatform $postPlatform): array
|
|||
];
|
||||
}
|
||||
|
||||
private function publishVideoPin(PostPlatform $postPlatform): array
|
||||
private function publishVideoPin(PostPlatform $postPlatform, ?string $content): array
|
||||
{
|
||||
$account = $postPlatform->socialAccount;
|
||||
$media = $postPlatform->media->first();
|
||||
|
|
@ -221,8 +223,8 @@ private function publishVideoPin(PostPlatform $postPlatform): array
|
|||
],
|
||||
];
|
||||
|
||||
if ($postPlatform->content) {
|
||||
$payload['description'] = $postPlatform->content;
|
||||
if ($content) {
|
||||
$payload['description'] = $content;
|
||||
}
|
||||
|
||||
if (! empty(data_get($postPlatform->meta, 'title'))) {
|
||||
|
|
@ -256,7 +258,7 @@ private function publishVideoPin(PostPlatform $postPlatform): array
|
|||
];
|
||||
}
|
||||
|
||||
private function publishCarousel(PostPlatform $postPlatform): array
|
||||
private function publishCarousel(PostPlatform $postPlatform, ?string $content): array
|
||||
{
|
||||
$account = $postPlatform->socialAccount;
|
||||
$medias = $postPlatform->media;
|
||||
|
|
@ -283,8 +285,8 @@ private function publishCarousel(PostPlatform $postPlatform): array
|
|||
],
|
||||
];
|
||||
|
||||
if ($postPlatform->content) {
|
||||
$payload['description'] = $postPlatform->content;
|
||||
if ($content) {
|
||||
$payload['description'] = $content;
|
||||
}
|
||||
|
||||
if (! empty(data_get($postPlatform->meta, 'title'))) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ public function publish(PostPlatform $postPlatform): array
|
|||
{
|
||||
$this->validateContentLength($postPlatform);
|
||||
|
||||
$content = $postPlatform->content ? app(ContentSanitizer::class)->sanitize($postPlatform->content, $postPlatform->platform) : null;
|
||||
|
||||
$account = $postPlatform->socialAccount;
|
||||
|
||||
// Refresh token if expired or expiring soon
|
||||
|
|
@ -40,8 +42,8 @@ public function publish(PostPlatform $postPlatform): array
|
|||
|
||||
$data = [];
|
||||
|
||||
if (! empty($postPlatform->content)) {
|
||||
$data['text'] = $postPlatform->content;
|
||||
if (! empty($content)) {
|
||||
$data['text'] = $content;
|
||||
}
|
||||
|
||||
$mediaIds = [];
|
||||
|
|
@ -65,7 +67,7 @@ public function publish(PostPlatform $postPlatform): array
|
|||
];
|
||||
}
|
||||
|
||||
if (empty($data['text'] ?? null) && empty($mediaIds)) {
|
||||
if (empty($content) && empty($mediaIds)) {
|
||||
throw new \Exception('X posts require either text or media. Please add content to your post.');
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue