fix: classify Pinterest content-policy rejections (code 1) instead of surfacing raw JSON (#278)

* fix: classify Pinterest content-policy rejections (code 1) instead of surfacing raw JSON

* fix: map documented Pinterest 404 responses to ContentPolicy category
This commit is contained in:
Paulo Castellano 2026-08-12 12:08:07 -03:00 committed by GitHub
parent de54ea24f9
commit 120839213c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 0 deletions

View file

@ -41,6 +41,32 @@ public static function fromApiResponse(mixed $response): static
);
}
// Documented for /pins, /media, and /boards alike (Pinterest's public
// OpenAPI spec: github.com/pinterest/api-description). In our flows
// this means the board (or, when polling media status, the media
// upload) referenced by the request no longer exists or isn't
// accessible to this account.
if ($status === 404) {
return new static(
userMessage: 'Pinterest could not find the selected board. It may have been deleted or you no longer have access to it.',
category: ErrorCategory::ContentPolicy,
platformErrorCode: (string) $status,
rawResponse: $rawResponse,
);
}
// Pinterest's own JSON error code 1 ("Sorry! This site doesn't allow
// you to save Pins.") is a content-policy rejection reused from their
// legacy "nopin" crawler-block message, not an HTTP/technical error.
if ($status === 400 && (int) data_get($body, 'code') === 1) {
return new static(
userMessage: "Pinterest rejected this pin. This usually means the content violates Pinterest's content policies (e.g. adult or sexual content).",
category: ErrorCategory::ContentPolicy,
platformErrorCode: (string) $status,
rawResponse: $rawResponse,
);
}
if ($status === 400 && str_contains(strtolower($rawResponse), 'board')) {
return new static(
userMessage: 'Invalid board. Please select a valid board.',

View file

@ -34,6 +34,26 @@
->and($exception->userMessage)->toBe('Not authorized to create pins on this board.');
});
test('HTTP 404 maps to ContentPolicy category', function () {
$response = Http::response(['code' => 2, 'message' => 'Board not found.'], 404);
$fakeResponse = Http::fake(['*' => $response])->post('https://api.pinterest.com/test');
$exception = PinterestPublishException::fromApiResponse($fakeResponse);
expect($exception->category)->toBe(ErrorCategory::ContentPolicy)
->and($exception->userMessage)->toBe('Pinterest could not find the selected board. It may have been deleted or you no longer have access to it.');
});
test('HTTP 400 with Pinterest error code 1 maps to ContentPolicy category', function () {
$response = Http::response(['code' => 1, 'message' => "Sorry! This site doesn't allow you to save Pins."], 400);
$fakeResponse = Http::fake(['*' => $response])->post('https://api.pinterest.com/test');
$exception = PinterestPublishException::fromApiResponse($fakeResponse);
expect($exception->category)->toBe(ErrorCategory::ContentPolicy)
->and($exception->userMessage)->toBe("Pinterest rejected this pin. This usually means the content violates Pinterest's content policies (e.g. adult or sexual content).");
});
test('HTTP 400 with board in body maps to ContentPolicy category', function () {
$response = Http::response(['message' => 'Invalid board_id provided.'], 400);
$fakeResponse = Http::fake(['*' => $response])->post('https://api.pinterest.com/test');