| | | 1 | | using System.Text.Json; |
| | | 2 | | using TeleFlow.Telegram.Schema.Types; |
| | | 3 | | |
| | | 4 | | namespace TeleFlow.Telegram.Internal; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Parses raw Telegram Bot API response bytes into an owned envelope used by the request executor. |
| | | 8 | | /// It keeps the parsed JSON document alive so successful result payloads can be deserialized without rematerializing JS |
| | | 9 | | /// </summary> |
| | | 10 | | internal sealed class TelegramTransportEnvelopeParser |
| | | 11 | | { |
| | | 12 | | private readonly JsonSerializerOptions _serializerOptions; |
| | | 13 | | |
| | | 14 | | public TelegramTransportEnvelopeParser(JsonSerializerOptions serializerOptions) |
| | | 15 | | { |
| | 302 | 16 | | ArgumentNullException.ThrowIfNull(serializerOptions); |
| | 302 | 17 | | _serializerOptions = serializerOptions; |
| | 302 | 18 | | } |
| | | 19 | | |
| | | 20 | | public bool TryParse( |
| | | 21 | | ReadOnlyMemory<byte> responseBody, |
| | | 22 | | out TelegramTransportEnvelope envelope, |
| | | 23 | | out JsonException? exception) |
| | | 24 | | { |
| | 87 | 25 | | JsonDocument? document = null; |
| | | 26 | | |
| | | 27 | | try |
| | | 28 | | { |
| | 87 | 29 | | document = JsonDocument.Parse(responseBody); |
| | 82 | 30 | | var root = document.RootElement; |
| | | 31 | | |
| | 82 | 32 | | var ok = root.TryGetProperty("ok", out var okElement) && okElement.ValueKind is JsonValueKind.True or JsonVa |
| | 82 | 33 | | ? okElement.GetBoolean() |
| | 82 | 34 | | : throw new JsonException("Telegram response does not contain a valid 'ok' property."); |
| | | 35 | | |
| | 82 | 36 | | var hasResult = root.TryGetProperty("result", out var resultElement); |
| | | 37 | | |
| | 82 | 38 | | string? description = null; |
| | 82 | 39 | | if (root.TryGetProperty("description", out var descriptionElement) && |
| | 82 | 40 | | descriptionElement.ValueKind == JsonValueKind.String) |
| | | 41 | | { |
| | 28 | 42 | | description = descriptionElement.GetString(); |
| | | 43 | | } |
| | | 44 | | |
| | 82 | 45 | | int? errorCode = null; |
| | 82 | 46 | | if (root.TryGetProperty("error_code", out var errorCodeElement) && |
| | 82 | 47 | | errorCodeElement.ValueKind == JsonValueKind.Number && |
| | 82 | 48 | | errorCodeElement.TryGetInt32(out var parsedErrorCode)) |
| | | 49 | | { |
| | 28 | 50 | | errorCode = parsedErrorCode; |
| | | 51 | | } |
| | | 52 | | |
| | 82 | 53 | | ResponseParameters? responseParameters = null; |
| | 82 | 54 | | if (root.TryGetProperty("response_parameters", out var responseParametersElement)) |
| | | 55 | | { |
| | 9 | 56 | | responseParameters = JsonSerializer.Deserialize<ResponseParameters>( |
| | 9 | 57 | | responseParametersElement, |
| | 9 | 58 | | _serializerOptions); |
| | | 59 | | } |
| | | 60 | | |
| | 82 | 61 | | envelope = new TelegramTransportEnvelope( |
| | 82 | 62 | | document, |
| | 82 | 63 | | ok, |
| | 82 | 64 | | hasResult, |
| | 82 | 65 | | resultElement, |
| | 82 | 66 | | description, |
| | 82 | 67 | | errorCode, |
| | 82 | 68 | | responseParameters); |
| | 82 | 69 | | document = null; |
| | 82 | 70 | | exception = null; |
| | 82 | 71 | | return true; |
| | | 72 | | } |
| | 5 | 73 | | catch (JsonException jsonException) |
| | | 74 | | { |
| | 5 | 75 | | envelope = null!; |
| | 5 | 76 | | exception = jsonException; |
| | 5 | 77 | | return false; |
| | | 78 | | } |
| | | 79 | | finally |
| | | 80 | | { |
| | 87 | 81 | | document?.Dispose(); |
| | 87 | 82 | | } |
| | 87 | 83 | | } |
| | | 84 | | } |