예제 #1
0
 private void OnMessageProcessed(Session session, Response response)
 {
     MessageProcessed?.Invoke(this, new MessageProcessedEventArgs()
     {
         Session = session, Parameter = response
     });
 }
예제 #2
0
        public void Receive()
        {
            MessageProcessed.Reset();

            try
            {
                Socket.BeginReceive(State.Buffer, 0, Constants.BufferSize, 0,
                                    FinalizeReceive, State);
            }
            catch (Exception e)
            {
                if (e is SocketException socketException &&
                    socketException.SocketErrorCode == SocketError.ConnectionReset)
                {
                    HandleExpectedConnectionError(new IdentifiableCommunicationException(Id, "Receive error - socket closed", e,
                                                                                         CommunicationException.ErrorSeverity.Temporary));
                    return;
                }
                if (e is ObjectDisposedException)
                {
                    HandleExpectedConnectionError(new IdentifiableCommunicationException(Id, "Disposed during Send", e, CommunicationException.ErrorSeverity.Temporary));
                    return;
                }

                ConnectionError.PrintUnexpectedConnectionErrorDetails(e);
                throw;
            }

            MessageProcessed.WaitOne();
        }
 private void OnMessageProcessed(Session session)
 {
     MessageProcessed?.Invoke(this, new MessageProcessedEventArgs()
     {
         Session = session
     });
 }
예제 #4
0
        private void Consumer_Received(object sender, BasicDeliverEventArgs ea)
        {
            try
            {
                _semaphore.Wait();
                LocationWriteDataQueue message = _objectDataConverter.JsonToObject <LocationWriteDataQueue>(Encoding.UTF8.GetString(ea.Body));
                MessageReceived?.Invoke(this, message);

                Task.Run(() =>
                {
                    try
                    {
                        var task = _locationInfoService.FileWritingOperation(message);
                        task.Wait();
                        var result = task.Result;
                        MessageProcessed?.Invoke(this, result);
                    }
                    catch (Exception ex)
                    {
                        //log
                        //throw new Exception(ex.InnerException.Message.ToString());
                    }
                    finally
                    {
                        _channel.BasicAck(ea.DeliveryTag, false);
                        _semaphore.Release();
                    }
                });
            }
            catch (Exception ex)
            {
                //loglama
                //throw new Exception(ex.InnerException.Message.ToString());
            }
        }
예제 #5
0
 private void Consumer_Received(object sender, BasicDeliverEventArgs ea)
 {
     try
     {
         _semaphore.Wait();
         MailMessageData message = _objectConvertFormat.JsonToObject <MailMessageData>(Encoding.UTF8.GetString(ea.Body));
         MessageReceived?.Invoke(this, message);
         // E-Posta akışını başlatma yeri
         Task.Run(() =>
         {
             try
             {
                 var task = _mailSender.SendMailAsync(message);
                 task.Wait();
                 var result = task.Result;
                 MessageProcessed?.Invoke(this, result);
             }
             catch (Exception ex)
             {
                 throw new Exception(ex.InnerException.Message.ToString());
             }
             finally
             {
                 // Teslimat Onayı
                 _channel.BasicAck(ea.DeliveryTag, false);
                 // akışı - thread'i serbest bırakıyoruz ek thread alabiliriz.
                 _semaphore.Release();
             }
         });
     }
     catch (Exception ex)
     {
         throw new Exception(ex.InnerException.Message.ToString());
     }
 }
예제 #6
0
 public void FireMessageProcessedEvent()
 {
     if (MessageProcessed != null)
     {
         MessageProcessed.Invoke(this);
     }
 }
예제 #7
0
 private void Execute(MessageProcessed msg)
 {
     if (_messagesToWaitFor.Any())
     {
         _messagesToWaitFor.Remove(msg.MessageType);
         if (!_messagesToWaitFor.Any())
         {
             Next();
         }
     }
 }
예제 #8
0
        public async Task HandleCommand(Payload cmdPayload, PowerPilotCommon.Models.PostgreSQL.Connection connection)
        {
            foreach (Payload.Types.Metric metric in cmdPayload.Metrics)
            {
                if (metric.Name == $"{DeviceCommands.TYPE}/{DeviceCommands.REBIRTH}")
                {
                    var downlink = await BuildDBIRTH(connection);

                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DBIRTH, connection.DeviceEUI), downlink.ToByteArray()));
                }
            }
        }
예제 #9
0
        // Обработка приходящих сообщений
        private void Vk_MessageReceived(object sender, MessageEventArgs e)
        {
            // Добавление в Users, если отсутствует
            if (!Users.Contains(e.Message.Id))
            {
                Task.Delay(300).Wait();
                var name = vk.GetUsername(e.Message.Id);
                if (name != null)
                {
                    Users.AddUser(e.Message.Id, name, null);
                }
            }

            // Вызов события о новом сообщении
            MessageReceived?.Invoke(this, e);

            // Пинаем каждый модуль чтоб он обработал сообщения
            for (int i = 0; i < Extensions.Length; i++)
            {
                var extension = Extensions[i];

                // Скипаем выключенные модули
                if (!extension.Enabled)
                {
                    continue;
                }

                // Передаём модулям сообщения для обработки
                MessageProcessing?.Invoke(this, new MessageProcessedEventArgs(extension));
                var res = extension.ProcessMessage(e.Message.Id, e.Message.Text);
                // Логирование и остановка обработки
                if (res == ProcessResult.Processed)
                {
                    MessageProcessed?.Invoke(this, new MessageProcessedEventArgs(extension));
                    if (extension.StopAfterProcessed)
                    {
                        ExtensionStopProcessing?.Invoke(this, new MessageProcessedEventArgs(extension));
                        return;
                    }
                }
                else if (res == ProcessResult.Skipped)
                {
                    MessageSkipped?.Invoke(this, new MessageProcessedEventArgs(extension));
                }
            }
        }
예제 #10
0
        public void OnMQTTClientConnected(object sender, EventArgs e)
        {
            if (!nbirth_sent)
            {
                Payload payload = new Payload()
                {
                    Seq       = GetSeq(),
                    Timestamp = (ulong)DateTimeOffset.Now.ToUnixTimeSeconds()
                };

                //namespace/group_id/message_type/edge_node_id
                //$"spBv1.0/DTX/{SparkPlugMessageTypes.NBIRTH}/PowerPilotCS";
                var topic = string.Format(_publishTopic, SparkPlugMessageTypes.NBIRTH, "").TrimEnd('/');
                MessageProcessed?.Invoke(this, new MQTTMessageArgs(topic, payload.ToByteArray()));

                nbirth_sent = true;
            }
        }
 private async Task ProcessMessages(CancellationToken cancellationToken)
 {
     foreach (var message in _messageQueue.GetConsumingEnumerable(cancellationToken))
     {
         _logger.LogDebug(FormattableString.Invariant($"Processing message..."));
         if (_configuration.TryGetMapping(message.Address, out var mapping))
         {
             try
             {
                 await _restClient.InvokeService(mapping, cancellationToken);
             }
             catch (Exception ex) when(!cancellationToken.IsCancellationRequested)
             {
                 _logger.LogError(FormattableString.Invariant($"Error invoking REST service for mapping. Key='{mapping.Key}'{Environment.NewLine}{ex}"));
             }
         }
         MessageProcessed?.Invoke(this, EventArgs.Empty);
     }
 }
예제 #12
0
        // Цикл обработки сообщений
        private void MessageProcessingLoop()
        {
            while (scriptProcessor.State != Interpreter.ExecutionState.Finished)
            {
                var    messageToProcess = messages.Take();
                string eventName        = GetScriptEventNameForMessage(messageToProcess);

                // Подготовить данные для обработки скриптом
                if (eventName != null)
                {
                    var player    = session.GetPlayerById(messageToProcess.SenderId);
                    var eventData = messageToProcess.ToDictionary();

                    if (player != null)
                    {
                        // Если задан ID игрока - передать его место за столом
                        eventData.Add(PlayerIndexField, player.SeatIndex);
                    }

                    object results = null;
                    try
                    {
                        results = scriptProcessor.RaiseEvent(eventName, eventData);
                    }
                    catch (Exception e)
                    {
                        var exceptionArgs = new ScriptErrorEventArgs(e);
                        ScriptErrorOccured?.Invoke(this, exceptionArgs);
                    }

                    if (results != null && results is object[])
                    {
                        // Обработка результатов
                        var resultsList = results as object[];
                        var changes     = resultsTranslator.Translate(resultsList);

                        // Вызвать обработчики события
                        var eventArgs = new MessageProcessedEventArgs(changes);
                        MessageProcessed?.Invoke(this, eventArgs);
                    }
                }
            }
        }
예제 #13
0
        void IConnectorBase <Message> .Send(MessageProcessed <Message> message, IMessagingService service)
        {
            try
            {
                var msg = "";
                if (!string.IsNullOrEmpty(message.Message.Subject))
                {
                    msg += $"Тема: {message.Message.Subject}\r\n\r\n";
                }
                msg += message.Message.Body?.ToString();
                msg  = msg.Truncate(0, 4096);

                var username = message.Message.To.ContactData?.Replace("@", "");

                if (!_usersChatsList.ContainsKey(username))
                {
                    throw new HandledException($"Пользователь '{username}' не найден в списке контактов бота '{_botUser.Username}'.");
                }

                var d  = getClient().SendTextMessageAsync(_usersChatsList[username], msg.Trim()).WaitAndReturn();
                var dd = d;

                message.IsHandled = true;
                message.IsSuccess = true;
            }
            catch (HandledException ex)
            {
                service.RegisterServiceEvent(Journaling.EventType.Error, "Telegram - ошибка отправки сообщения", ex.Message, ex.InnerException);
                message.IsError   = false;
                message.ErrorText = ex.Message;
            }
            catch (Exception ex)
            {
                service.RegisterServiceEvent(Journaling.EventType.Error, "Telegram - необработанная ошибка отправки сообщения", null, ex);
                Debug.WriteLine(ex.ToString());
                message.IsError   = false;
                message.ErrorText = "Необработанная ошибка во время отправки сообщения";
            }
        }
        private void Consumer_Received(object sender, BasicDeliverEventArgs ea)
        {
            try
            {
                _semaphore.Wait();
                LocationReadDataQueue message = _objectDataConverter.JsonToObject <LocationReadDataQueue>(Encoding.UTF8.GetString(ea.Body));
                MessageReceived?.Invoke(this, message);

                Task.Run(() =>
                {
                    try
                    {
                        var task = _locationInfoService.GetLocationsDistanceAsync(message);
                        task.Wait();
                        var result = task.Result;

                        var insertedTask = _locationInfoService.QueueDatabaseCreatedAfterSendFileProcess(result);
                        insertedTask.Wait();

                        MessageProcessed?.Invoke(this, result);
                    }
                    catch (Exception ex)
                    {
                        //throw new Exception(ex.InnerException.Message.ToString());
                    }
                    finally
                    {
                        _channel.BasicAck(ea.DeliveryTag, false);
                        _semaphore.Release();
                    }
                });
            }
            catch (Exception ex)
            {
                throw new Exception(ex.InnerException.Message.ToString());
            }
        }
예제 #15
0
        /// <summary>
        /// Обработка события получения сообщений.
        /// Разблокировка метода (для дальнейшего получения сообщений из брокера) происходит
        /// по завершению обработки сообщения и высвобождению вакантного потока.
        /// </summary>
        private void Consumer_Received(object sender, BasicDeliverEventArgs ea)
        {
            /// Ожидание вакантного потока для продолжения выполнения метода
            _semaphore.Wait();

            var message = ParseMailMessageData(ea.Body);

            MessageReceived?.Invoke(this, message);

            /// Запуск потока отправки письма
            Task.Run(() => {
                try {
                    var task = _mailSender.SendMailAsync(message);
                    task.Wait();
                    var result = task.Result;
                    MessageProcessed?.Invoke(this, result);
                } finally {
                    /// Подтверждение доставки
                    _channel.BasicAck(ea.DeliveryTag, false);
                    /// Высвобождение потока
                    _semaphore.Release();
                }
            });
        }
예제 #16
0
 static void CompletedProcessing(MessageProcessed message)
 {
     message.Completion.SetResult(message.ProcessedValue);
 }
예제 #17
0
        /// <inheritdoc cref="IMailClient.SendAsync(IMessageBuilder, IDataRecord, IEnumerable{IMessageMutator}, CancellationToken)"/>
        protected virtual async Task <(MimeMessage?Message, bool Stop)> SendAsyncImpl(IMessageBuilder messageBuilder, IDataRecord record, IEnumerable <IMessageMutator> messageMutators, IFormatProvider formatProvider, int index, int count, CancellationToken cancellationToken)
        {
            IMessageBuilder message = messageBuilder.Clone();

            FormatMessage(message, record, formatProvider);
            foreach (IMessageMutator mutator in messageMutators)
            {
                try
                {
                    message = mutator.Mutate(message, record);
                }
                catch (Exception e)
                {
                    MessageMutationErrorEventArgs errorArgs = new MessageMutationErrorEventArgs(message, mutator, e);
                    MessageMutationError?.Invoke(this, errorArgs);
                    if (errorArgs.Stop)
                    {
                        return(null, true);
                    }
                    else if (errorArgs.Skip)
                    {
                        MessageProcessed?.Invoke(this, new MessageProcessedEventArgs(message.ToMessage(), index, count, ProcessedType.Skipped));
                        return(null, false);
                    }
                    else if (errorArgs.SkipMutation)
                    {
                        continue;
                    }
                    throw;
                }
            }

            BeforeMessageSentEventArgs beforeArgs = new BeforeMessageSentEventArgs(message);

            BeforeMessageSent?.Invoke(this, beforeArgs);
            if (beforeArgs.Stop)
            {
                return(null, true);
            }
            else if (beforeArgs.Skip)
            {
                MessageProcessed?.Invoke(this, new MessageProcessedEventArgs(message.ToMessage(), index, count, ProcessedType.Skipped));
                return(null, false);
            }

            MimeMessage result  = message.ToMessage();
            int         attempt = 0;

            while (true)
            {
                try
                {
                    ITransferProgress transferProgress = new TransferProgress((bytesTransferred, totalSize) =>
                                                                              MessageTransferProgress?.Invoke(this, new MessageTransferProgressEventArgs(result, bytesTransferred, totalSize)));

                    await Client.SendAsync(result, cancellationToken, progress : transferProgress).ConfigureAwait(false);

                    MessageSent?.Invoke(this, new MessageSentEventArgs(result));
                    MessageProcessed?.Invoke(this, new MessageProcessedEventArgs(result, index, count, ProcessedType.Sent));
                    return(result, false);
                }
                catch (Exception e)
                {
                    MessageTransferErrorEventArgs errorArgs = new MessageTransferErrorEventArgs(result, e, ++attempt);
                    MessageTransferError?.Invoke(this, errorArgs);
                    if (errorArgs.Stop)
                    {
                        return(null, true);
                    }
                    else if (errorArgs.Skip)
                    {
                        MessageProcessed?.Invoke(this, new MessageProcessedEventArgs(result, index, count, ProcessedType.Skipped));
                        return(null, false);
                    }
                    else if (errorArgs.Retry)
                    {
                        continue;
                    }
                    throw;
                }
            }
        }
예제 #18
0
        public async void ProcessMessage(object sender, MQTTMessageArgs args)
        {
            try
            {
                string[] parts       = args.Topic.Split("/");
                string   deviceEUI   = null;
                string   messageType = null;
                if (parts[0] == "application")
                {
                    // application/powerpilot/uplink/{type}/{deviceEUI}
                    messageType = parts[3];
                    deviceEUI   = parts[4];
                }
                else if (parts[0] == "spBv1.0")
                {
                    // spBv1.0/DTX/{0}/PowerPilotCS/{1}
                    messageType = parts[2];
                    deviceEUI   = parts[4];
                }

                if (deviceEUI == null)
                {
                    _loggerClient.LogError($"Could not get device eui from {args.Topic}", "ProcessMessage", Pplogger.ErrorMessage.Types.Severity.Fatal);
                    return;
                }

                // check if this device exists in our system
                var connection = await _dataService.GetConnection(deviceEUI);

                if (connection == null)
                {
                    return;
                }

                Payload payload = new Payload()
                {
                    Seq       = GetSeq(),
                    Timestamp = (ulong)DataServiceClient.ConvertToTimestamp(DateTime.Now)
                };

                // check if we have this deviceEUI already, if not then send DBIRTH
                // use lock to avoid concurrent adds
                bool added = false;
                lock (dbirthLock)
                {
                    if (!deviceEUIs.Contains(deviceEUI))
                    {
                        deviceEUIs.Add(deviceEUI);
                        added = true;
                    }
                }

                if (added)
                {
                    var dbirthPayload = await BuildDBIRTH(connection);

                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DBIRTH, connection.DeviceEUI), dbirthPayload.ToByteArray()));
                    // return;
                }

                // var topic = $"spBv1.0/DTX/{SparkPlugMessageTypes.DDATA}/PowerPilotCS/{deviceEUI}";
                switch (messageType)
                {
                // sparkplug commands
                case SparkPlugMessageTypes.DCMD:
                    var cmd = Payload.Parser.ParseFrom(args.Payload);
                    await HandleCommand(cmd, connection);

                    break;

                // powerpilot messages
                case TopicNames.ENERGY:
                    var energy        = Ppuplink.EnergyMessage.Parser.ParseFrom(args.Payload);
                    var energyPayload = AddEnergyMetrics(energy, payload);
                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DDATA, deviceEUI), energyPayload.ToByteArray()));
                    break;

                case TopicNames.PQ:
                    var pq        = Ppuplink.PQMessage.Parser.ParseFrom(args.Payload);
                    var pqPayload = AddPQMetrics(pq, payload, connection);
                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DDATA, deviceEUI), pqPayload.ToByteArray()));
                    break;

                case TopicNames.INST:
                    var inst = Ppuplink.InstMessage.Parser.ParseFrom(args.Payload);
                    // not interested yet
                    break;

                case TopicNames.ALARM:
                    var alarm        = Ppuplink.AlarmMessage.Parser.ParseFrom(args.Payload);
                    var alarmPayload = AddAlarmMetrics(alarm, payload, connection);
                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DDATA, deviceEUI), alarmPayload.ToByteArray()));

                    //if power fail also need DDEATH
                    if (alarm.Alarmtype == "powerfailalarm")
                    {
                        var ddeathPayload = BuildDDEATH(alarm);
                        var ddeath_topic  = string.Format(_publishTopic, SparkPlugMessageTypes.DDEATH, deviceEUI);   // $"spBv1.0/DTX/{SparkPlugMessageTypes.DDEATH}/PowerPilotCS/{deviceEUI}";
                        MessageProcessed?.Invoke(this, new MQTTMessageArgs(ddeath_topic, ddeathPayload.ToByteArray()));
                    }
                    //if normal voltage then also need DBIRTH
                    else if (alarm.Alarmtype == "normalvoltage")
                    {
                        var dbirthPayload = await BuildDBIRTH(connection);

                        MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DBIRTH, connection.DeviceEUI), dbirthPayload.ToByteArray()));
                    }

                    break;

                case TopicNames.UPLINK:
                    var uplink        = Ppuplink.UplinkMessage.Parser.ParseFrom(args.Payload);
                    var uplinkPayload = AddUplinkMetrics(uplink, payload);
                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DDATA, deviceEUI), uplinkPayload.ToByteArray()));
                    break;

                case TopicNames.VOLTAGE_STATS:
                    var vs        = Ppuplink.VoltageStatsMessage.Parser.ParseFrom(args.Payload);
                    var vsPayload = AddVoltageStatsMetrics(vs, payload, connection);
                    MessageProcessed?.Invoke(this, new MQTTMessageArgs(string.Format(_publishTopic, SparkPlugMessageTypes.DDATA, deviceEUI), vsPayload.ToByteArray()));
                    break;

                default:
                    _loggerClient.LogMessage($"Not processing type {messageType}");
                    break;
                }
            }
            catch (Exception ex)
            {
                _loggerClient.LogError($"Exception while processing Message: {ex.Message}", "ProcessMessage", Pplogger.ErrorMessage.Types.Severity.Fatal);
                if (ex.StackTrace != null)
                {
                    _loggerClient.LogMessage(ex.StackTrace);
                }
                return;
            }
        }
        /// <summary>
        /// Raise a <see cref="MessageProcessed"/> event
        /// </summary>
        /// <param name="e">Send the <see cref="FeedMessage"/> originally received</param>
        protected void RaiseOnMessageProcessedEvent(FeedMessageReceivedEventArgs e)
        {
            Contract.Requires(e != null);

            MessageProcessed?.Invoke(this, e);
        }
예제 #20
0
        protected virtual void FinalizeReceive(IAsyncResult ar)
        {
            var state     = ar.AsyncState as CommunicationState;
            var handler   = Socket;
            var bytesRead = 0;

            try
            {
                bytesRead = handler.EndReceive(ar);
            }
            catch (Exception e)
            {
                if (e is SocketException socketException &&
                    socketException.SocketErrorCode == SocketError.ConnectionReset)
                {
                    HandleExpectedConnectionError(new IdentifiableCommunicationException(Id, "Read error - socket closed", e,
                                                                                         CommunicationException.ErrorSeverity.Temporary));
                    return;
                }

                if (e is ObjectDisposedException)
                {
                    throw new IdentifiableCommunicationException(Id, "Disposed during FinalizeReceive", e, CommunicationException.ErrorSeverity.Temporary);
                }

                ConnectionError.PrintUnexpectedConnectionErrorDetails(e);
                throw;
            }

            if (bytesRead > 0)
            {
                var(messages, hasEtbByte) = state.SplitMessages(bytesRead, Id);
                State.UpdateLastReceivedMessageTicks();

                foreach (var message in messages)
                {
                    if (!string.IsNullOrEmpty(message))
                    {
                        try
                        {
                            Handle(MessageDeserializer.Deserialize(message), Id);
                        }
                        catch (Exception e)
                        {
                            throw new IdentifiableCommunicationException(Id, "Encountered error while deserializing message", e, CommunicationException.ErrorSeverity.Temporary);
                        }
                    }
                }

                //DONT TOUCH THAT
                //DANGER ZONE ************
                if (!hasEtbByte)
                {
                    try
                    {
                        handler.BeginReceive(state.Buffer, 0, Constants.BufferSize, 0,
                                             FinalizeReceive, state);
                    }
                    catch (Exception e)
                    {
                        ConnectionError.PrintUnexpectedConnectionErrorDetails(e);
                        throw;
                    }
                }
                else
                {
                    MessageProcessed.Set();
                }

                // ManualResetEvent (Semaphore) is signaled only when whole message was received,
                // allowing another thread to start evaluating FinalizeReceive. Otherwise the same thread
                // continues to read the rest of the message
                //DANGER ZONE ****************
            }
        }
        /// <summary>
        /// Raise a <see cref="MessageProcessed"/> event
        /// </summary>
        /// <param name="e">Send the <see cref="FeedMessage"/> originally received</param>
        protected void RaiseOnMessageProcessedEvent(FeedMessageReceivedEventArgs e)
        {
            Guard.Argument(e, nameof(e)).NotNull();

            MessageProcessed?.Invoke(this, e);
        }
예제 #22
0
파일: AmazonSNS.cs 프로젝트: Sellec/OnXap
        public void Send(MessageProcessed <Message> message, IMessagingService service)
        {
            try
            {
                if (string.IsNullOrEmpty(message.ExternalID))
                {
                    var smsAttributes = new Dictionary <string, MessageAttributeValue>();

                    MessageAttributeValue senderID = new MessageAttributeValue();
                    senderID.DataType    = "String";
                    senderID.StringValue = Routing.UrlManager.Translate(AppCore.Config.SiteShortName)?.Truncate(0, 11);
                    if (string.IsNullOrEmpty(senderID.StringValue))
                    {
                        senderID.StringValue = "Site";
                    }

                    MessageAttributeValue sMSType = new MessageAttributeValue();
                    sMSType.DataType    = "String";
                    sMSType.StringValue = "Transactional";

                    smsAttributes.Add("AWS.SNS.SMS.SenderID", senderID);
                    smsAttributes.Add("AWS.SNS.SMS.SMSType", sMSType);

                    var responseTask = getClientSNS().PublishAsync(new PublishRequest()
                    {
                        Message           = message.Message.Body?.ToString(),
                        PhoneNumber       = message.Message.To.ContactData,
                        MessageAttributes = smsAttributes
                    });
                    responseTask.Wait();
                    var response = responseTask.Result;

                    message.IsHandled  = true;
                    message.ExternalID = response.MessageId;
                }
                else
                {
                    var logGroupName = _options.GetOrAddWithExpiration("LogGroupName", (k) =>
                    {
                        try
                        {
                            var preferencesTask = getClientSNS().GetSMSAttributesAsync(new GetSMSAttributesRequest()
                            {
                                Attributes = new List <string>()
                                {
                                    "DeliveryStatusIAMRole"
                                }
                            });
                            preferencesTask.Wait();
                            var preferences = preferencesTask.Result;
                            if (preferences != null && preferences.Attributes != null && preferences.Attributes.Count > 0)
                            {
                                var val           = preferences.Attributes["DeliveryStatusIAMRole"];
                                var roleNameMatch = System.Text.RegularExpressions.Regex.Match(preferences.Attributes["DeliveryStatusIAMRole"], "arn:aws:iam::([^:]+):role");
                                if (!roleNameMatch.Success)
                                {
                                    service.RegisterServiceEvent(Journaling.EventType.Error, "Ошибка получения роли IAM для логирования событий отправки SMS", "Возможно, изменился формат названия роли. Ожидался формат \"arn:aws:iam::xxxxxxxxxxxx:role\".");
                                    return(string.Empty);
                                }
                                else
                                {
                                    var name = $"sns/{getClientCloudWatchLogs().Config.RegionEndpoint.SystemName }/{roleNameMatch.Groups[1].Value}/DirectPublishToPhoneNumber";
                                    return(name);
                                }
                            }
                            else
                            {
                                service.RegisterServiceEvent(Journaling.EventType.Warning, "Ошибка получения данных о настройках", "В настройках Amazon SNS / Text messaging (SMS) не задана роль IAM для ведения логов в Amazon CloudWatch. Зайдите в консоль управления в раздел \"Amazon SNS / Text messaging (SMS) / Manage text messaging preferences\", проверьте пункт \"IAM role for CloudWatch Logs access\". Если в нем есть только ссылка \"Create IAM role\", следует перейти по ней и настроить роль IAM.");
                                return(string.Empty);
                            }
                        }
                        catch (Exception ex)
                        {
                            service.RegisterServiceEvent(Journaling.EventType.Warning, "Неожиданная ошибка получения данных о настройках", null, ex);
                            Debug.WriteLine(ex);
                            return(string.Empty);
                        }
                    }, TimeSpan.FromMinutes(5));

                    if (!string.IsNullOrEmpty(logGroupName))
                    {
                        try
                        {
                            var taskRr = getClientCloudWatchLogs().FilterLogEventsAsync(new FilterLogEventsRequest()
                            {
                                LogGroupName = logGroupName, FilterPattern = "{ $.notification.messageId = \"" + message.ExternalID + "\" }"
                            });
                            taskRr.Wait();
                            var rr = taskRr.Result;
                            if (rr != null && rr.Events != null && rr.Events.Count > 0)
                            {
                                if (!string.IsNullOrEmpty(rr.Events.First().Message) && rr.Events.First().Message.Contains("\"status\":\"SUCCESS\""))
                                {
                                    message.IsHandled = true;
                                    message.IsSuccess = true;
                                }
                            }
                        }
                        catch (AmazonCloudWatchLogsException ex)
                        {
                            if (ex.ErrorCode == "AccessDeniedException")
                            {
                                service.RegisterServiceEvent(Journaling.EventType.Warning, "Ошибка получения статуса доставки", "Доступ запрещен - возможно, у используемого IAM-ключа недостаточно прав для чтения данных из Amazon CloudWatch", ex);
                            }
                            else
                            {
                                throw;
                            }
                            //if (ex.)
                            //Amazon.CloudWatchLogs.AmazonCloudWatchLogsException: User: arn: aws: iam::036187153096:user / Dombonus is not authorized to perform: logs: FilterLogEvents on resource: arn: aws: logs: us - west - 2:036187153096:log - group:sns / us - west - 2 / 036187153096 / DirectPublishToPhoneNumber:log -
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
            }
            catch (HandledException ex)
            {
                service.RegisterServiceEvent(Journaling.EventType.Error, "Amazon SNS - ошибка отправки сообщения", ex.Message, ex.InnerException);
                message.IsError   = false;
                message.ErrorText = ex.Message;
            }
            catch (Exception ex)
            {
                service.RegisterServiceEvent(Journaling.EventType.Error, "Telegram - необработанная ошибка отправки сообщения", null, ex);
                Debug.WriteLine(ex.ToString());
                message.IsError   = false;
                message.ErrorText = "Необработанная ошибка во время отправки сообщения";
            }
        }