From 491895cbd9a7772b794cdeb8647beade67c4cfe9 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Fri, 24 Jul 2026 22:12:50 -0300 Subject: [PATCH] Page through all Pinterest boards until the bookmark ends. Replace the 20-page hard stop with a while-loop that follows bookmarks to completion, keeping only safety breaks for a repeated cursor or an absurd page ceiling. Co-authored-by: Cursor --- app/Services/Social/PinterestPublisher.php | 37 ++++++++++++++++--- .../Social/PinterestPublisherTest.php | 35 +++++++++++++++++- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/app/Services/Social/PinterestPublisher.php b/app/Services/Social/PinterestPublisher.php index 6efa47b0..dbbf5743 100644 --- a/app/Services/Social/PinterestPublisher.php +++ b/app/Services/Social/PinterestPublisher.php @@ -405,7 +405,8 @@ private function waitForMediaProcessing(SocialAccount $account, string $mediaId, } /** - * Get user's boards for board selection (follows Pinterest bookmark pagination). + * Get user's boards for board selection (follows Pinterest bookmark pagination + * until the API stops returning a bookmark). * * @return list> */ @@ -417,9 +418,23 @@ public function getBoards(SocialAccount $account): array $boards = []; $bookmark = null; - $maxPages = 20; + $pages = 0; + // Absurd ceiling only — normal accounts exit when bookmark is blank. + $maxPages = 1000; + + while (true) { + $pages++; + + if ($pages > $maxPages) { + Log::warning('Pinterest get boards hit safety page cap', [ + 'account_id' => $account->id, + 'pages' => $pages, + 'boards' => count($boards), + ]); + + break; + } - for ($page = 0; $page < $maxPages; $page++) { $query = ['page_size' => 100]; if (filled($bookmark)) { @@ -441,11 +456,23 @@ public function getBoards(SocialAccount $account): array array_push($boards, ...$items); } - $bookmark = data_get($payload, 'bookmark'); + $nextBookmark = data_get($payload, 'bookmark'); - if (blank($bookmark)) { + if (blank($nextBookmark)) { break; } + + if ($nextBookmark === $bookmark) { + Log::warning('Pinterest get boards returned a repeated bookmark', [ + 'account_id' => $account->id, + 'pages' => $pages, + 'boards' => count($boards), + ]); + + break; + } + + $bookmark = $nextBookmark; } return $boards; diff --git a/tests/Feature/Services/Social/PinterestPublisherTest.php b/tests/Feature/Services/Social/PinterestPublisherTest.php index e2d62ef3..1d5b9ac5 100644 --- a/tests/Feature/Services/Social/PinterestPublisherTest.php +++ b/tests/Feature/Services/Social/PinterestPublisherTest.php @@ -531,14 +531,45 @@ 'items' => [ ['id' => 'board_2', 'name' => 'Board 2'], ], + 'bookmark' => 'page-3', + ], 200) + ->push([ + 'items' => [ + ['id' => 'board_3', 'name' => 'Board 3'], + ], + ], 200), + ]); + + $boards = $this->publisher->getBoards($this->socialAccount); + + expect($boards)->toHaveCount(3) + ->and($boards[0]['id'])->toBe('board_1') + ->and($boards[1]['id'])->toBe('board_2') + ->and($boards[2]['id'])->toBe('board_3'); + + Http::assertSentCount(3); +}); + +test('pinterest publisher stops board pagination on a repeated bookmark', function () { + Http::fake([ + config('trypost.platforms.pinterest.api').'/boards*' => Http::sequence() + ->push([ + 'items' => [['id' => 'board_1', 'name' => 'Board 1']], + 'bookmark' => 'stuck', + ], 200) + ->push([ + 'items' => [['id' => 'board_2', 'name' => 'Board 2']], + 'bookmark' => 'stuck', + ], 200) + ->push([ + 'items' => [['id' => 'should_not_fetch', 'name' => 'Nope']], ], 200), ]); $boards = $this->publisher->getBoards($this->socialAccount); expect($boards)->toHaveCount(2) - ->and($boards[0]['id'])->toBe('board_1') - ->and($boards[1]['id'])->toBe('board_2'); + ->and(collect($boards)->pluck('id')->all())->toBe(['board_1', 'board_2']); Http::assertSentCount(2); });