using portaloggy; using System.Text; using System.Text.Json.Nodes; namespace MessengerApi.Contracts { /// /// Exists for mocking reason. This is implemented by . /// public interface IMessengerClient { /// /// Receives pending messages from the messenger API. /// /// Credentials to the API. IEnumerable GetMessages(); /// /// Acknowledges message reception to the server. /// void AckMessage(InboxMessage message); /// /// Sends a message. /// /// Credentials to the API. void SendMessage(OutboxMessage outboxMessage); /// /// Returns user ids for allowed message recipients. /// Contact[] GetYellowPages(); } public class MessengerClient : IMessengerClient { private readonly HttpClient _httpClient; private readonly ILogger _logger; private DateTime _lastReceivedUtc; private Credentials _credentials; public MessengerClient(Credentials credentials, HttpClient httpClient = null, ILogger logger = null) { _credentials = credentials; _httpClient = httpClient ?? new HttpClient(); _logger = logger ?? new ConsoleLogger(); _lastReceivedUtc = DateTime.MinValue.ToUniversalTime(); } public IEnumerable GetMessages() { var since = Uri.EscapeDataString(this._lastReceivedUtc.ToString("o")); var url = $"{_credentials.ApiUrl}/receive?sinceUtc={since}"; var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _credentials.ApiKey); _logger.Debug($"Sending query to {url} with content {request.ToString()} to obtain messages."); var response = _httpClient.Send(request); if (!response.IsSuccessStatusCode) { _logger.Error(response.ReasonPhrase); throw new HttpRequestException("Can't receive.", null, response.StatusCode); } var responseContent = response.Content .ReadAsStringAsync() .GetAwaiter() .GetResult(); if (!string.IsNullOrWhiteSpace(responseContent)) { _logger.Debug($"Received response of {responseContent}."); } if (string.IsNullOrWhiteSpace(responseContent)) { return Enumerable.Empty().ToArray(); } var json = JsonNode.Parse(responseContent); var messages = new List(); foreach (var item in json["messages"].AsArray()) { if (item["id"].GetValue() == -1) { continue; } messages.Add(new InboxMessage { Id = item["id"].GetValue(), Payload = item["payload"].ToJsonString(), PayloadType = item["payloadType"].ToJsonString(), Sender = item["sender"].GetValue(), }); } _lastReceivedUtc = DateTime.UtcNow.Subtract(TimeSpan.FromSeconds(10)); _logger.Debug($"Received {messages.Count} messages and last check timestamp is set to {_lastReceivedUtc.ToString("s")}."); return messages.ToArray(); } public void SendMessage(OutboxMessage outboxMessage) { var body = new JsonObject(); if(outboxMessage.ToUserId.HasValue) { body.Add("toUserId", JsonValue.Create(outboxMessage.ToUserId.Value)); } if(outboxMessage.Payload != null) { body.Add("payload", JsonValue.Create(outboxMessage.Payload)); } if(outboxMessage.PayloadType != null) { body.Add("payloadType", JsonValue.Create(outboxMessage.PayloadType)); } if(outboxMessage.LifespanInSeconds != null) { body.Add("lifespanInSeconds", JsonValue.Create(outboxMessage.LifespanInSeconds.Value)); } var content = new StringContent(body.ToString(), Encoding.UTF8, "application/json"); var url = $"{_credentials.ApiUrl}/send"; var request = new HttpRequestMessage(HttpMethod.Post, url); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _credentials.ApiKey); _logger.Debug($"Sending query to {url} with content {body.ToString()} to obtain messages."); var response = _httpClient.Send(request); if (!response.IsSuccessStatusCode) { _logger.Error(response.ReasonPhrase); throw new HttpRequestException("Can't send.", null, response.StatusCode); } } public Contact[] GetYellowPages() { var url = $"{_credentials.ApiUrl}/yellowpages"; var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _credentials.ApiKey); _logger.Debug($"Sending query to {url} with content {request.ToString()}."); var response = _httpClient.Send(request); if (!response.IsSuccessStatusCode) { _logger.Error(response.ReasonPhrase); throw new HttpRequestException("Can't receive.", null, response.StatusCode); } var responseContent = response.Content .ReadAsStringAsync() .GetAwaiter() .GetResult(); var json = JsonNode.Parse(responseContent); var contacts = json["users"].AsArray().Select(x => new Contact { Id = x["id"].GetValue(), Name = x["name"].GetValue() }).ToArray(); return contacts; } public void AckMessage(InboxMessage message) { } } }