Пример #1
0
        /// <summary>
        /// Выполнить команду
        /// </summary>
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            if (!(args is RecordingEventArgs eventArgs))
            {
                throw new ArgumentException($"RecordingStartedCommand. Incorrect argument type {nameof(args)}");
            }

            try
            {
                var audioRecord = await AudioRecordRepository.GetRecordByName(eventArgs.RecordName);

                if (audioRecord != null)
                {
                    audioRecord.RecordingStartTime = eventArgs.EventTime;
                    await AudioRecordRepository.UpdateRecord(audioRecord);
                }
                else
                {
                    Logger.Warning($"RecordingStartedCommand. AudioRecord not found. RecordName: {eventArgs.RecordName}.");
                }
            }
            catch (Exception ex)
            {
                Logger.Warning("RecordingStartedCommand.Error.", ex);
            }
        }
Пример #2
0
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            var lineId = args.RouteData?.LineId;

            if (!lineId.HasValue)
            {
                Logger.Warning("SwitchRolesCommand. Не найден LineId.");
                throw new Exception("Не найден LineId");
            }

            var oldMainChannel = await ChannelRepository.GetChannelForMainUser(lineId.Value);

            if (oldMainChannel == null)
            {
                Logger.Warning("SwitchRolesCommand. Не найден канал главного в разговоре.");
                throw new Exception("Не найден канал главного в разговоре");
            }

            if (oldMainChannel.CallId != args.RouteData.FromCallId)
            {
                Logger.Warning($"SwitchRolesCommand. Пользователь звонка {args.RouteData.FromCallId} не является главным в разговоре. MainUserCallId: {oldMainChannel.CallId}");
                throw new Exception($"Пользователь звонка с Id {args.RouteData.FromCallId} не является главным в разговоре");
            }

            var assistantChannel = await ChannelRepository.GetChannelByCallId(args.RouteData.ToCallId);

            if (assistantChannel == null)
            {
                Logger.Warning($"SwitchRolesCommand. Канал с Id {args.RouteData.ToCallId} не найден.");
                throw new Exception($"Канал с Id {args.RouteData.ToCallId} не найден.");
            }

            await ChangeMainChannel(oldMainChannel, assistantChannel, lineId.Value, args);
        }
Пример #3
0
        /// <summary>
        /// Выполнить команду
        /// </summary>
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            if (!(args is RecordingEventArgs eventArgs))
            {
                throw new ArgumentException($"RecordingEndedCommand. Incorrect argument type {nameof(args)}");
            }

            try
            {
                var audioRecord = await AudioRecordRepository.GetRecordByName(eventArgs.RecordName);

                if (audioRecord == null || audioRecord.RecordingStartTime.HasValue == false)
                {
                    Logger.Warning($"Record with name {eventArgs.RecordName} not found");
                    return;
                }

                Logger.Information($"Audio record created. RecordName: {eventArgs.RecordName};");
                await _queueSender.Publish(new AudioRecordedIntegrationEvent
                {
                    LineId             = audioRecord.LineId,
                    CallId             = audioRecord.CallId,
                    FileName           = $"{eventArgs.RecordName}.{AsteriskAriClient.RecordingFormat}",
                    RecordingStartTime = audioRecord.RecordingStartTime.Value,
                    RecordingEndTime   = eventArgs.EventTime
                });

                audioRecord.RecordingEndTime = eventArgs.EventTime;
                await AudioRecordRepository.UpdateRecord(audioRecord);
            }
            catch (Exception ex)
            {
                Logger.Warning("RecordingEndedCommand.Error.", ex);
            }
        }
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel incomingCallChannel, StasisStartEventArgs args)
        {
            var callerExtension = incomingCallChannel.Caller.Number;
            var callId          = Guid.NewGuid();

            var mainBridge = await InitializeMainBridge(incomingCallChannel.Id, callerExtension, callId);

            if (mainBridge == null)
            {
                return;
            }

            var channel = new DAL.Entities.Channel
            {
                ChannelId = incomingCallChannel.Id,
                Extension = callerExtension,
                CallId    = callId,
                BridgeId  = mainBridge,
                Role      = ChannelRoleType.ExternalChannel
            };

            var bNumber = incomingCallChannel.Dialplan.Exten;
            await _queueSender.Publish(new IncomingCallIntegrationEvent
            {
                CallId          = callId,
                CallerExtension = callerExtension,
                BNumber         = bNumber,
            });

            Logger.Information($"Sent message to queue about incoming call. Caller: {callerExtension}; ChannelId: {incomingCallChannel.Id}");

            await ChannelRepository.AddChannel(channel);
        }
Пример #5
0
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel userChannel, StasisStartEventArgs args)
        {
            var routeData = args.RouteData;

            if (!routeData.FromCallId.HasValue)
            {
                Logger.Warning($"Id вызова пользователя не задан. ChannelId: {userChannel.Id}");
                return;
            }

            var userExtension        = routeData.FromExtension;
            var destinationExtension = routeData.ToExtension;
            var destinationChannelId = AriClient.CreateChannelId(ChannelRoleType.ExternalChannel, destinationExtension);

            var bridge = await AriClient.CreateBridge();

            await AriClient.AddChannelToBridge(bridge.Id, userChannel.Id);

            var playBackId = await AriClient.PlayBeeps(userChannel.Id);

            var destinationCallArgs = new StasisStartEventArgs
            {
                BridgeId   = bridge.Id,
                EventType  = StasisStartEventType.CallToDestination,
                RouteData  = routeData,
                PlaybackId = playBackId
            };

            var encodedArgs     = JsonSerializer.EncodeData(destinationCallArgs);
            var originateResult = await AriClient.Originate(encodedArgs, "Служба 112", destinationExtension, destinationChannelId);

            if (!originateResult)
            {
                throw new Exception("Ошибка создания канала для участника разговора, которому звонит пользователь.");
            }

            var userChannelEntity = new DAL.Entities.Channel
            {
                ChannelId = userChannel.Id,
                Extension = userExtension,
                CallId    = routeData.FromCallId.Value,
                BridgeId  = bridge.Id,
                Role      = ChannelRoleType.Conference,
                LineId    = routeData.LineId
            };
            await ChannelRepository.AddChannel(userChannelEntity);

            var destinationChannelEntity = new DAL.Entities.Channel
            {
                ChannelId = destinationChannelId,
                Extension = destinationExtension,
                CallId    = routeData.ToCallId,
                BridgeId  = bridge.Id,
                Role      = ChannelRoleType.RingingFromUser,
                LineId    = routeData.LineId
            };
            await ChannelRepository.AddChannel(destinationChannelEntity);
        }
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel destinationChannel, StasisStartEventArgs args)
        {
            var routeData = args.RouteData;

            Logger.Information($"AcceptedCallFromUserCommand. DestinationChannelId: {destinationChannel.Id}, UserChannelId: {args.ChannelId}");

            try
            {
                var destinationExtension     = routeData.ToExtension;
                var destinationChannelEntity = await ChannelRepository.GetByChannelId(destinationChannel.Id);

                if (destinationChannelEntity == null)
                {
                    Logger.Warning($"Канал вызываемого участника не найден. ChannelId: {destinationChannel.Id}");
                    return;
                }

                var channelsInBridge = await ChannelRepository.GetByBridgeId(destinationChannelEntity.BridgeId);

                var userChannel = channelsInBridge.SingleOrDefault(x => x.Role == ChannelRoleType.Conference);
                if (userChannel == null)
                {
                    Logger.Warning($"Канал пользователя не найден. LineId: {routeData.LineId}");
                    return;
                }

                var callId = destinationChannelEntity.CallId;

                await StartCallRecording(userChannel.ChannelId, userChannel.CallId, userChannel.Extension, userChannel.Role, userChannel.BridgeId, routeData.LineId);
                await InitializeRecordingChannel(destinationChannel.Id, destinationExtension, destinationChannelEntity.Role, userChannel.BridgeId, callId, routeData.LineId);

                destinationChannelEntity.Role = ChannelRoleType.ExternalChannel;
                await ChannelRepository.UpdateChannel(destinationChannelEntity);

                await AriClient.StopBeeps(args.PlaybackId);

                await AriClient.AddChannelToBridge(userChannel.BridgeId, destinationChannel.Id);

                Logger.Information($"Участник разговора {destinationExtension} принял вызов от пользователя {userChannel.Extension}");
                await _queueSender.Publish(new AcceptCallFromUserIntegrationEvent
                {
                    CallId = callId
                });
            }
            catch (Exception ex)
            {
                Logger.Warning("AcceptedCallFromUserCommand Error", ex);
            }
        }
Пример #7
0
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel userChannel, StasisStartEventArgs args)
        {
            Logger.Information($"AcceptIncomingCallCommand. UserChannelId: {userChannel.Id}, IncomingChannelId: {args.ChannelId}");

            try
            {
                var incomingCallChannel = await ChannelRepository.GetByChannelId(args.ChannelId);

                if (incomingCallChannel == null)
                {
                    Logger.Warning($"Канал входящего вызова не найден. UserChannelId: {userChannel.Id}");
                    return;
                }

                var routeData = args.RouteData;
                var lineId    = routeData.LineId;

                await InitializeRecordingChannel(userChannel.Id, routeData.ToExtension, ChannelRoleType.Conference, incomingCallChannel.BridgeId, routeData.ToCallId, lineId);

                await AriClient.UnholdAsync(incomingCallChannel.ChannelId);

                await AriClient.StopMohInBridgeAsync(incomingCallChannel.BridgeId);

                await AriClient.AddChannelToBridge(incomingCallChannel.BridgeId, userChannel.Id);

                incomingCallChannel.Interrupted = false;
                incomingCallChannel.LineId      = lineId;
                await ChannelRepository.UpdateChannel(incomingCallChannel);

                await UpdateAudioRecords(incomingCallChannel.BridgeId, incomingCallChannel.CallId, lineId);

                var userChannelEntity = new DAL.Entities.Channel
                {
                    ChannelId = userChannel.Id,
                    BridgeId  = incomingCallChannel.BridgeId,
                    CallId    = routeData.ToCallId,
                    Extension = routeData.ToExtension,
                    Role      = ChannelRoleType.Conference,
                    LineId    = lineId
                };
                await ChannelRepository.AddChannel(userChannelEntity);
            }
            catch (Exception ex)
            {
                Logger.Warning("AcceptIncomingCallCommand Error", ex);
            }
        }
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            Logger.Information($"DeleteChannel. Id: {channel.Id}");

            var channelEntity = await ChannelRepository.GetByChannelId(channel.Id);

            if (channelEntity == null)
            {
                Logger.Warning($"Канал не найден или был удален ранее. ChannelId: {channel.Id}");
                return;
            }

            await NotifyIfIncomingCallEnded(channelEntity);

            await DeleteChannel(channelEntity);
            await DestroyBridge(channelEntity.BridgeId);
        }
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            Logger.Information($"AddToSnoopBridge. Bridge: {args.BridgeId}. Channel: {args.ChannelId}");

            await AriClient.AddChannelToBridge(args.BridgeId, args.ChannelId);

            var channelEntity = new DAL.Entities.Channel
            {
                ChannelId         = args.ChannelId,
                BridgeId          = args.BridgeId,
                Role              = args.EventType == StasisStartEventType.AddToSpeakSnoopBridge ? ChannelRoleType.SpeakSnoopChannel : ChannelRoleType.SnoopChannel,
                LineId            = args.RouteData.LineId,
                CallId            = args.RouteData.ToCallId,
                OriginalChannelId = args.OriginalChannelId,
                Extension         = args.RouteData.ToExtension
            };

            await ChannelRepository.AddChannel(channelEntity);
        }
Пример #10
0
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            var channelId = channel.Id;

            Logger.Information($"RejectedCallFromUserCommand. DestinationChannelId: {channel.Id}");

            try
            {
                var destinationChannel = await ChannelRepository.GetByChannelId(channelId);

                if (destinationChannel == null || destinationChannel.Role != ChannelRoleType.RingingFromUser)
                {
                    Logger.Debug($"RejectedCallFromUserCommand. Канал участника уничтожен. CallId: {destinationChannel?.CallId}. {destinationChannel?.Role}");
                    return;
                }

                await ChannelRepository.DeleteChannel(destinationChannel.ChannelId);

                var channelsInBridge = await ChannelRepository.GetByBridgeId(destinationChannel.BridgeId);

                var userChannel = channelsInBridge.SingleOrDefault(x => x.Role == ChannelRoleType.Conference);
                if (userChannel == null)
                {
                    Logger.Warning("RejectedCallFromUserCommand. Канал пользователя не найден.");
                    return;
                }

                await AriClient.HangupChannel(userChannel.ChannelId);

                Logger.Information($"Отправка информации о том, что участник не принял или отклонил вызов от пользователя. Destination: {destinationChannel.Extension}");
                await _queueSender.Publish(new RejectCallIntegrationEvent
                {
                    CallId = destinationChannel.CallId
                });
            }
            catch (Exception ex)
            {
                Logger.Warning("RejectedCallFromUserCommand Error", ex);
            }
        }
Пример #11
0
        /// <inheritdoc />
        protected override async Task InternalExecute(Channel channel, StasisStartEventArgs args)
        {
            var routeData = args.RouteData;

            if (!routeData.LineId.HasValue)
            {
                return;
            }

            await AriClient.Answer(channel.Id);

            await InitializeRecordingChannel(channel.Id, routeData.ToExtension, ChannelRoleType.Conference, args.BridgeId, routeData.ToCallId, routeData.LineId);

            var bridge = await AriClient.GetBridge(args.BridgeId);

            await AriClient.AddChannelToBridge(bridge.Id, channel.Id);

            await SnoopChannelByAllAssistantsChannels(channel.Id, routeData.ToExtension, ChannelRoleType.Conference, routeData.ToCallId, args);

            Logger.Information($"Channel added to call in conference mode. ChannelId: {channel.Id}. CallId: {routeData.ToCallId}");

            var channelForIncomingCall = await ChannelRepository.GetChannelForIncomingCall(routeData.LineId.Value);

            if (channelForIncomingCall != null && channelForIncomingCall.Interrupted)
            {
                channelForIncomingCall.Interrupted = false;
                await ChannelRepository.UpdateChannel(channelForIncomingCall);
            }

            var channelEntity = new DAL.Entities.Channel
            {
                ChannelId = channel.Id,
                BridgeId  = args.BridgeId,
                CallId    = routeData.ToCallId,
                Extension = routeData.ToExtension,
                Role      = ChannelRoleType.Conference,
                LineId    = routeData.LineId
            };
            await ChannelRepository.AddChannel(channelEntity);
        }
Пример #12
0
        /// <summary>
        /// Создать новую пару бриджей (LISTEN/SPEAK) для ассистента/частичного ассистента и добавить туда каналы для прослушивания/разговора
        /// </summary>
        protected async Task <DAL.Entities.Channel> CreateNewAssistantBridgesAndSnoop(Channel assistantChannel,
                                                                                      StasisStartEventArgs args, ChannelRoleType assistantRole)
        {
            var lineId = args.RouteData?.LineId;

            if (!lineId.HasValue)
            {
                Logger.Warning($"CallTo{assistantRole}. LineId не найден AssistantChannelId: {assistantChannel.Id}.");
                return(null);
            }

            var mainChannel = await ChannelRepository.GetChannelForMainUser(lineId.Value);

            if (mainChannel == null)
            {
                Logger.Warning($"CallTo{assistantRole}. MainChannel не найден.");
                return(null);
            }

            var assistantExtension = args.RouteData.ToExtension;
            var assistantCallId    = args.RouteData.ToCallId;
            var prefix             = assistantRole == ChannelRoleType.PartialAssistant ? "PASSISTANT" : "ASSISTANT";
            var assistantBridgeId  = $"{prefix}_{assistantExtension}_{assistantChannel.Id}";
            var speakBridgeId      = $"{assistantBridgeId}_SPEAK";
            var listenBridgeId     = $"{assistantBridgeId}_LISTEN";

            await InitializeRecordingChannel(assistantChannel.Id, args.RouteData.ToExtension, assistantRole, mainChannel.BridgeId, assistantCallId, lineId.Value);

            await AriClient.CreateBridge(speakBridgeId);

            await AriClient.CreateBridge(listenBridgeId);

            await AriClient.AddChannelToBridge(listenBridgeId, assistantChannel.Id);

            await InitializeSnoopChannel(assistantChannel.Id, assistantExtension, assistantRole, assistantCallId, speakBridgeId, args, SnoopBridgeType.Speak, true);

            var channelsInLine = await ChannelRepository.GetChannelsByLineId(lineId.Value);

            var channelsInMainBridge     = channelsInLine.Where(t => t.BridgeId == mainChannel.BridgeId).ToList();
            var partialAssistantChannels = channelsInLine.Where(t => t.Role == ChannelRoleType.PartialAssistant).ToList();

            foreach (var channel in channelsInMainBridge)
            {
                await InitializeSnoopChannel(channel.ChannelId, channel.Extension, channel.Role, channel.CallId, listenBridgeId, args, SnoopBridgeType.Listen);

                if (NeedAddChannelToSpeakBridge(channel.Role, assistantRole))
                {
                    await InitializeSnoopChannel(channel.ChannelId, channel.Extension, channel.Role, channel.CallId, speakBridgeId, args, SnoopBridgeType.Speak);
                }
            }

            foreach (var channel in partialAssistantChannels)
            {
                await InitializeSnoopChannel(channel.ChannelId, channel.Extension, channel.Role, channel.CallId, listenBridgeId, args, SnoopBridgeType.Listen);

                if (assistantRole == ChannelRoleType.PartialAssistant)
                {
                    await InitializeSnoopChannel(channel.ChannelId, channel.Extension, channel.Role, channel.CallId, speakBridgeId, args, SnoopBridgeType.Speak);
                }
            }

            if (assistantRole == ChannelRoleType.PartialAssistant)
            {
                await SnoopChannelByAllAssistantsChannels(assistantChannel.Id, assistantExtension, assistantRole, assistantCallId, args);
            }

            var assistantChannelEntity = new DAL.Entities.Channel
            {
                ChannelId = assistantChannel.Id,
                Extension = assistantExtension,
                CallId    = assistantCallId,
                BridgeId  = listenBridgeId,
                Role      = assistantRole,
                LineId    = lineId.Value
            };
            await ChannelRepository.AddChannel(assistantChannelEntity);

            return(assistantChannelEntity);
        }
Пример #13
0
 /// <summary>
 /// Реализация команды
 /// </summary>
 protected abstract Task InternalExecute(Channel channel, StasisStartEventArgs args);
Пример #14
0
 /// <summary>
 /// Выполнить команду
 /// </summary>
 public async Task Execute(Channel channel, StasisStartEventArgs args)
 {
     await InternalExecute(channel, args);
 }
Пример #15
0
 /// <inheritdoc />
 protected override async Task InternalExecute(Channel assistantChannel, StasisStartEventArgs args)
 {
     await CreateNewAssistantBridgesAndSnoop(assistantChannel, args, ChannelRoleType.Assistant);
 }