|
33 | 33 | use BushlanovDev\MaxMessengerBot\Models\UploadEndpoint;
|
34 | 34 | use BushlanovDev\MaxMessengerBot\Models\VideoAttachmentDetails;
|
35 | 35 | use InvalidArgumentException;
|
| 36 | +use JsonException; |
36 | 37 | use LogicException;
|
37 | 38 | use Psr\Log\LoggerInterface;
|
38 | 39 | use Psr\Log\NullLogger;
|
@@ -470,27 +471,51 @@ public function uploadAttachment(UploadType $type, string $filePath): AbstractAt
|
470 | 471 |
|
471 | 472 | $uploadEndpoint = $this->getUploadUrl($type);
|
472 | 473 |
|
473 |
| - $uploadResult = $this->client->upload( |
474 |
| - $uploadEndpoint->url, |
475 |
| - $fileHandle, |
476 |
| - basename($filePath), |
477 |
| - ); |
| 474 | + // For audio and video, the token is received *before* the upload |
| 475 | + // The actual upload response is not JSON and can be ignored on success |
| 476 | + if ($type === UploadType::Audio || $type === UploadType::Video) { |
| 477 | + if (empty($uploadEndpoint->token)) { |
| 478 | + throw new SerializationException( |
| 479 | + "API did not return a pre-upload token for type '$type->value'." |
| 480 | + ); |
| 481 | + } |
| 482 | + $this->client->upload($uploadEndpoint->url, $fileHandle, basename($filePath)); |
| 483 | + fclose($fileHandle); |
478 | 484 |
|
| 485 | + return match ($type) { |
| 486 | + UploadType::Audio => new AudioAttachmentRequest($uploadEndpoint->token), |
| 487 | + UploadType::Video => new VideoAttachmentRequest($uploadEndpoint->token), |
| 488 | + }; |
| 489 | + } |
| 490 | + |
| 491 | + // For images and files, the token is in the response *after* the upload. |
| 492 | + $responseBody = $this->client->upload($uploadEndpoint->url, $fileHandle, basename($filePath)); |
479 | 493 | fclose($fileHandle);
|
480 | 494 |
|
481 |
| - if (!isset($uploadResult['token'])) { |
482 |
| - throw new SerializationException('Could not find "token" in upload server response.'); |
| 495 | + try { |
| 496 | + $uploadResult = json_decode($responseBody, true, 512, JSON_THROW_ON_ERROR); |
| 497 | + } catch (JsonException $e) { |
| 498 | + throw new SerializationException('Failed to decode upload server response JSON.', 0, $e); |
| 499 | + } |
| 500 | + |
| 501 | + // Using switch because match expression arms cannot be code blocks. |
| 502 | + switch ($type) { |
| 503 | + case UploadType::Image: |
| 504 | + $photoData = current($uploadResult['photos'] ?? []); // Get first photo from response |
| 505 | + if (!isset($photoData['token'])) { |
| 506 | + throw new SerializationException('Could not find "token" in photo upload response.'); |
| 507 | + } |
| 508 | + return PhotoAttachmentRequest::fromToken($photoData['token']); |
| 509 | + case UploadType::File: |
| 510 | + if (!isset($uploadResult['token'])) { |
| 511 | + throw new SerializationException('Could not find "token" in file upload response.'); |
| 512 | + } |
| 513 | + return new FileAttachmentRequest($uploadResult['token']); |
483 | 514 | }
|
484 | 515 |
|
485 |
| - return match ($type) { |
486 |
| - UploadType::Image => PhotoAttachmentRequest::fromToken($uploadResult['token']), |
487 |
| - UploadType::Video => new VideoAttachmentRequest($uploadResult['token']), |
488 |
| - UploadType::Audio => new AudioAttachmentRequest($uploadResult['token']), |
489 |
| - UploadType::File => new FileAttachmentRequest($uploadResult['token']), // @phpstan-ignore-line |
490 |
| - default => throw new LogicException( |
491 |
| - "Attachment creation for type '$type->value' is not yet implemented." |
492 |
| - ), |
493 |
| - }; |
| 516 | + // @codeCoverageIgnoreStart |
| 517 | + throw new LogicException("Attachment creation for type '$type->value' is not yet implemented."); // @phpstan-ignore-line |
| 518 | + // @codeCoverageIgnoreEnd |
494 | 519 | }
|
495 | 520 |
|
496 | 521 | /**
|
|
0 commit comments