Revert "Update Bird module to use AccessKey authorization header instead of Bearer, improve error handling, and add support for workspace/channel configuration."

This reverts commit 2ad9bcfd37.
This commit is contained in:
Jeppe Bundgaard
2026-02-27 03:09:48 +01:00
parent 2ad9bcfd37
commit 1087ffb413
8 changed files with 50 additions and 218 deletions
+12 -85
View File
@@ -11,7 +11,6 @@ class bird
{
public const TEST_OUTBOUND_NUMBER_RAW = '+45 42 33 11 28';
public const TEST_OUTBOUND_NUMBER_E164 = '+4542331128';
private const ALLOWED_HANGUP_CAUSES = ['rejected', 'busy'];
/**
* Configuration of the Bird module
@@ -97,9 +96,9 @@ class bird
$url = rtrim($this->config->server_url->getVariableValue(), '/') . $endpoint;
$headers = [
'Content-Type: application/json',
$this->buildAuthorizationHeader(),
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
];
$body = $this->encodeJsonBody($data);
$body = json_encode($data);
$this->logBirdAction(
'BIRD_HTTP_REQUEST',
@@ -111,7 +110,7 @@ class bird
$this->logBirdAction('BIRD_HTTP_RESPONSE', 'method=POST endpoint=' . $endpoint . ' status=' . $status);
if ($status >= 400) {
$this->logBirdAction('BIRD_HTTP_ERROR', 'method=POST endpoint=' . $endpoint . ' status=' . $status, 0);
throw new Exception($this->buildHttpErrorMessage($status, $response));
throw new Exception('Bird API request failed with status ' . $status);
}
if ($response === '' || $response === false || $response === null) {
return null;
@@ -180,7 +179,7 @@ class bird
}
$headers = [
'Content-Type: application/json',
$this->buildAuthorizationHeader(),
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
];
$this->logBirdAction(
'BIRD_HTTP_REQUEST',
@@ -192,7 +191,7 @@ class bird
$this->logBirdAction('BIRD_HTTP_RESPONSE', 'method=GET endpoint=' . $endpoint . ' status=' . $status);
if ($status >= 400) {
$this->logBirdAction('BIRD_HTTP_ERROR', 'method=GET endpoint=' . $endpoint . ' status=' . $status, 0);
throw new Exception($this->buildHttpErrorMessage($status, $response));
throw new Exception('Bird API request failed with status ' . $status);
}
if ($response === '' || $response === false || $response === null) {
return null;
@@ -210,9 +209,9 @@ class bird
$url = rtrim($this->config->server_url->getVariableValue(), '/') . $endpoint;
$headers = [
'Content-Type: application/json',
$this->buildAuthorizationHeader(),
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
];
$body = $this->encodeJsonBody($data);
$body = json_encode($data);
$this->logBirdAction(
'BIRD_HTTP_REQUEST',
@@ -224,7 +223,7 @@ class bird
$this->logBirdAction('BIRD_HTTP_RESPONSE', 'method=PATCH endpoint=' . $endpoint . ' status=' . $status);
if ($status >= 400) {
$this->logBirdAction('BIRD_HTTP_ERROR', 'method=PATCH endpoint=' . $endpoint . ' status=' . $status, 0);
throw new Exception($this->buildHttpErrorMessage($status, $response));
throw new Exception('Bird API request failed with status ' . $status);
}
if ($response === '' || $response === false || $response === null) {
return null;
@@ -247,7 +246,7 @@ class bird
}
$headers = [
'Content-Type: application/json',
$this->buildAuthorizationHeader(),
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
];
$this->logBirdAction(
'BIRD_HTTP_REQUEST',
@@ -259,7 +258,7 @@ class bird
$this->logBirdAction('BIRD_HTTP_RESPONSE', 'method=DELETE endpoint=' . $endpoint . ' status=' . $status);
if ($status >= 400) {
$this->logBirdAction('BIRD_HTTP_ERROR', 'method=DELETE endpoint=' . $endpoint . ' status=' . $status, 0);
throw new Exception($this->buildHttpErrorMessage($status, $response));
throw new Exception('Bird API request failed with status ' . $status);
}
if ($response === '' || $response === false || $response === null) {
return null;
@@ -315,8 +314,7 @@ class bird
$maxAttempts = (int)max(1, floor($maxPollSeconds / $pollIntervalSeconds));
$payload = $options;
// Keep polling/hangup controls out of create-call payload to avoid Bird validation errors.
unset($payload['pollIntervalSeconds'], $payload['maxPollSeconds'], $payload['hangupCause']);
unset($payload['pollIntervalSeconds'], $payload['maxPollSeconds']);
$payload['to'] = self::TEST_OUTBOUND_NUMBER_E164;
$this->logBirdAction(
@@ -352,10 +350,7 @@ class bird
if ($status !== null && in_array(strtolower($status), $acceptedStates, true)) {
$hangupPayload = [];
if (isset($options['hangupCause']) && is_string($options['hangupCause']) && $options['hangupCause'] !== '') {
$normalizedCause = strtolower(trim($options['hangupCause']));
if (in_array($normalizedCause, self::ALLOWED_HANGUP_CAUSES, true)) {
$hangupPayload['cause'] = $normalizedCause;
}
$hangupPayload['cause'] = $options['hangupCause'];
}
$hangupResponse = $this->hangupVoiceCall($workspaceId, $channelId, $callId, $hangupPayload);
$this->logBirdAction('BIRD_TEST_OUTBOUND_CALL_HANGUP_SENT', 'call=' . $callId . ' status=' . $status);
@@ -421,71 +416,6 @@ class bird
return null;
}
private function buildHttpErrorMessage(int $status, string|false|null $response): string
{
$base = 'Bird API request failed with status ' . $status;
if (!is_string($response) || trim($response) === '') {
return $base;
}
$decoded = json_decode($response, true);
if (is_array($decoded)) {
$details = [];
foreach (['message', 'error', 'description'] as $key) {
if (isset($decoded[$key]) && is_string($decoded[$key]) && trim($decoded[$key]) !== '') {
$details[] = trim($decoded[$key]);
}
}
if (isset($decoded['errors'])) {
if (is_string($decoded['errors']) && trim($decoded['errors']) !== '') {
$details[] = trim($decoded['errors']);
} elseif (is_array($decoded['errors'])) {
foreach ($decoded['errors'] as $error) {
if (is_string($error) && trim($error) !== '') {
$details[] = trim($error);
} elseif (is_array($error) && isset($error['message']) && is_string($error['message']) && trim($error['message']) !== '') {
$details[] = trim($error['message']);
}
}
}
}
$details = array_values(array_unique(array_filter($details)));
if (!empty($details)) {
return $base . ': ' . implode(' | ', $details);
}
}
$snippet = preg_replace('/\s+/', ' ', trim($response));
if (!is_string($snippet) || $snippet === '') {
return $base;
}
if (strlen($snippet) > 220) {
$snippet = substr($snippet, 0, 220) . '...';
}
return $base . ': ' . $snippet;
}
private function buildAuthorizationHeader(): string
{
$apiKey = trim((string)$this->config->api_key->getVariableValue());
if ($apiKey === '') {
return 'Authorization: AccessKey';
}
if (preg_match('/^(Bearer|AccessKey)\s+/i', $apiKey) === 1) {
return 'Authorization: ' . $apiKey;
}
return 'Authorization: AccessKey ' . $apiKey;
}
private function encodeJsonBody(array $data): string
{
// Bird control endpoints expect an object payload; use {} for empty body.
if ($data === []) {
return '{}';
}
return json_encode($data);
}
private function logBirdAction(string $action, string $message, int $type = 1): void
{
try {
@@ -507,6 +437,3 @@ class bird
}
}
}