using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.Extensions.Logging; namespace GreenHome.Sms.Ippanel; /// /// IPPanel SMS service implementation /// public sealed class IppanelSmsService : ISmsService { private readonly HttpClient httpClient; private readonly IppanelSmsOptions options; private readonly ILogger logger; public IppanelSmsService( HttpClient httpClient, IppanelSmsOptions options, ILogger logger) { this.httpClient = httpClient; this.options = options; this.logger = logger; } public async Task?> SendWebserviceSmsAsync( WebserviceSmsRequest request, CancellationToken cancellationToken = default) { try { // Split recipients by comma and create array var recipients = request.Recipient .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .ToList(); var payload = new { sending_type = "webservice", from_number = request.Sender ?? options.DefaultSender, @params = new { recipients }, message = request.Message }; var response = await httpClient.PostAsJsonAsync( "api/send", payload, cancellationToken); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync>( cancellationToken: cancellationToken); return result; } catch (HttpRequestException ex) { logger.LogError(ex, "Error sending webservice SMS to {Recipient}", request.Recipient); throw; } catch (Exception ex) { logger.LogError(ex, "Unexpected error sending webservice SMS"); throw; } } public async Task?> SendPatternSmsAsync( PatternSmsRequest request, CancellationToken cancellationToken = default) { try { var payload = new { sending_type = "pattern", code = request.PatternCode, from_number = request.Originator ?? options.DefaultSender ?? string.Empty, recipients = request.Recipients, @params = ToAnonymousObject(request.Variables) }; var response = await httpClient.PostAsJsonAsync( "api/send", payload, cancellationToken); //response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync>( cancellationToken: cancellationToken); return result; } catch (HttpRequestException ex) { logger.LogError(ex, "Error sending pattern SMS to {Recipient}", request.Recipients); throw; } catch (Exception ex) { logger.LogError(ex, "Unexpected error sending pattern SMS"); throw; } } public object ToAnonymousObject(Dictionary dictionary) { var type = dictionary.GetType(); var obj = new System.Dynamic.ExpandoObject(); var dict = obj as IDictionary; foreach (var item in dictionary) { dict.Add(item.Key, item.Value); } return obj; } public class IppanelApiResponse { [JsonPropertyName("data")] public T? Data { get; set; } [JsonPropertyName("meta")] public IppanelMeta Meta { get; set; } } public class IppanelMeta { [JsonPropertyName("status")] public bool Status { get; set; } [JsonPropertyName("message")] public string? Message { get; set; } [JsonPropertyName("message_parameters")] public List MessageParameters { get; set; } = new List(); [JsonPropertyName("message_code")] public string? MessageCode { get; set; } [JsonPropertyName("errors")] public Dictionary> Errors { get; set; } = new Dictionary>(); } // Specific data models for different response types public class IppanelData { [JsonPropertyName("message_outbox_ids")] public List MessageOutboxIds { get; set; } = new List(); } }