public async Task <IActionResult> AddSelfTestFailureEventToConferenceAsync(Guid conferenceId,
                                                                                   [FromBody] AddSelfTestFailureEventRequest addSelfTestFailureEventRequest)
        {
            var participantId = await GetIdForParticipantByUsernameInConference(conferenceId);

            try
            {
                var eventRequest = new ConferenceEventRequest
                {
                    Conference_id  = conferenceId.ToString(),
                    Participant_id = participantId.ToString(),
                    Event_id       = Guid.NewGuid().ToString(),
                    Event_type     = addSelfTestFailureEventRequest.EventType,
                    Time_stamp_utc = DateTime.UtcNow,
                    Reason         = $"Failed self-test ({addSelfTestFailureEventRequest.SelfTestFailureReason.DescriptionAttr()})"
                };
                await _videoApiClient.RaiseVideoEventAsync(eventRequest);

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#2
0
        /// <summary>
        /// This updates the VMRs for a conference when a participant joins or leaves a VMR
        /// </summary>
        /// <param name="conference"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        private async Task UpdateConferenceRoomParticipants(Conference conference, ConferenceEventRequest request)
        {
            if (!request.IsParticipantAndVmrEvent())
            {
                return;
            }

            var roomId        = long.Parse(request.ParticipantRoomId);
            var participantId = Guid.Parse(request.ParticipantId);


            switch (request.EventType)
            {
            case EventType.Joined:
                conference.AddParticipantToRoom(roomId, participantId);
                break;

            case EventType.Disconnected:
                await _consultationResponseTracker.ClearResponses(conference, participantId);

                conference.RemoveParticipantFromRoom(roomId, participantId);
                break;

            default: return;
            }

            await _conferenceCache.UpdateConferenceAsync(conference);
        }
示例#3
0
        public async Task Should_not_create_video_event_with_invalid_request()
        {
            var conferenceRequest = CreateConferenceRequest();
            var conference        = await CreateConference(conferenceRequest);

            const EventType EVENT_TYPE    = EventType.None;
            const int       EVENT_TYPE_ID = (int)EVENT_TYPE;

            var participant = conference.Participants.First(x => x.UserRole == UserRole.Individual);

            var request = new ConferenceEventRequest()
            {
                ConferenceId  = conference.Id.ToString(),
                EventId       = EVENT_TYPE_ID.ToString(),
                EventType     = EVENT_TYPE,
                ParticipantId = participant.Id.ToString(),
                Phone         = string.Empty,
                Reason        = HearingData.VIDEO_EVENT_REASON,
                TimeStampUtc  = DateTime.UtcNow,
                TransferFrom  = null,
                TransferTo    = null
            };

            var uri = ApiUriFactory.ConferenceEndpoints.CreateVideoEvent;

            await SendPostRequest(uri, RequestHelper.Serialise(request));

            VerifyResponse(HttpStatusCode.BadRequest, false);
        }
 public static bool ShouldSkipEventHandler(this ConferenceEventRequest conferenceEvent) =>
 !string.IsNullOrEmpty(conferenceEvent.Phone) ||
 conferenceEvent.EventType == EventType.ConnectingToConference ||
 conferenceEvent.EventType == EventType.ConnectingToEventHub ||
 conferenceEvent.EventType == EventType.CountdownFinished ||
 conferenceEvent.EventType == EventType.Help ||
 conferenceEvent.EventType == EventType.SelectingMedia;
        protected async Task CreateEvent(ConferenceEventRequest request)
        {
            var uri = ApiUriFactory.ConferenceEndpoints.CreateVideoEvent;

            await SendPostRequest(uri, RequestHelper.Serialise(request));

            VerifyResponse(HttpStatusCode.NoContent, true);
        }
        private static void GetRoomTypeEnums(ConferenceEventRequest request, out RoomType?transferTo,
                                             out RoomType?transferFrom)
        {
            var isTransferFromEnum = Enum.TryParse(request.TransferFrom, out RoomType transferFromEnum);
            var isTransferToEnum   = Enum.TryParse(request.TransferTo, out RoomType transferToEnum);

            transferFrom = isTransferFromEnum ? transferFromEnum : (RoomType?)null;
            transferTo   = isTransferToEnum ? transferToEnum : (RoomType?)null;
        }
 public ConferenceEventRequestBuilder()
 {
     _request = new ConferenceEventRequest()
     {
         EventId      = Guid.NewGuid().ToString(),
         Reason       = "Automated",
         TimeStampUtc = DateTime.UtcNow,
         TransferFrom = RoomType.WaitingRoom,
         TransferTo   = RoomType.WaitingRoom
     };
 }
示例#8
0
        public static bool IsParticipantAVmr(this ConferenceEventRequest request, Conference conference,
                                             out long roomId)
        {
            if (!long.TryParse(request.ParticipantId, out roomId))
            {
                return(false);
            }
            var id = roomId;

            return(conference.CivilianRooms.Any(x => x.Id == id));
        }
示例#9
0
 public ConferenceEventRequestBuilder()
 {
     _request = new ConferenceEventRequest()
     {
         ConferenceId  = Guid.NewGuid().ToString(),
         EventId       = Guid.NewGuid().ToString(),
         ParticipantId = Guid.NewGuid().ToString(),
         Reason        = HearingData.VIDEO_EVENT_REASON,
         TimeStampUtc  = DateTime.UtcNow
     };
 }
示例#10
0
 public ConferenceEventRequestBuilder(ConferenceDetailsResponse conference)
 {
     _conference = conference;
     _request    = new ConferenceEventRequest()
     {
         ConferenceId = conference.Id.ToString(),
         EventId      = Guid.NewGuid().ToString(),
         Reason       = HearingData.VIDEO_EVENT_REASON,
         TimeStampUtc = DateTime.UtcNow
     };
 }
示例#11
0
        private Task SendEventToVideoApi(ConferenceEventRequest request)
        {
            if (request.EventType == EventType.VhoCall)
            {
                return(Task.CompletedTask);
            }

            request = request.UpdateEventTypeForVideoApi();

            _logger.LogTrace("Raising video event: ConferenceId: {ConferenceId}, EventType: {EventType}",
                             request.ConferenceId, request.EventType);

            return(_videoApiClient.RaiseVideoEventAsync(request));
        }
示例#12
0
        public async Task <IActionResult> CreateEvent(ConferenceEventRequest request)
        {
            _logger.LogDebug($"CreateEvent");

            try
            {
                await _videoApiClient.RaiseVideoEventAsync(request);

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#13
0
     public static ConferenceEventRequest UpdateEventTypeForVideoApi(this ConferenceEventRequest request)
     {
         request.EventType = request.EventType switch
         {
             EventType.Joined when !request.ParticipantRoomId.IsNullOrEmpty() => EventType
             .RoomParticipantJoined,
                              EventType.Disconnected when !request.ParticipantRoomId.IsNullOrEmpty() => EventType
             .RoomParticipantDisconnected,
                              EventType.Transfer when !request.ParticipantRoomId.IsNullOrEmpty() => EventType
             .RoomParticipantTransfer,
                              _ => request.EventType
         };
         return(request);
     }
 }
示例#14
0
        private CallbackEvent TransformAndMapRequest(ConferenceEventRequest request, Conference conference)
        {
            var isPhoneEvent = string.IsNullOrEmpty(request.Phone);

            if (!isPhoneEvent)
            {
                return(null);
            }

            var callbackEventMapper = _mapperFactory.Get <ConferenceEventRequest, Conference, CallbackEvent>();
            var callbackEvent       = callbackEventMapper.Map(request, conference);

            request.EventType = Enum.Parse <EventType>(callbackEvent.EventType.ToString());

            return(callbackEvent);
        }
示例#15
0
        public async Task <IActionResult> CreateVideoEvent(ConferenceEventRequest request)
        {
            _logger.LogDebug("CreateVideoEvent");

            try
            {
                await _testApiClient.CreateEventAsync(request);

                return(NoContent());
            }
            catch (TestApiException e)
            {
                _logger.LogError(e, "Unable to create event: {eventType}", request.EventType);
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#16
0
        public async Task <IActionResult> UpdateParticipantStatusAsync(Guid conferenceId,
                                                                       UpdateParticipantStatusEventRequest updateParticipantStatusEventRequest)
        {
            var conference = await _conferenceCache.GetOrAddConferenceAsync(conferenceId, () =>
            {
                _logger.LogTrace($"Retrieving conference details for conference: ${conferenceId}");

                return(_videoApiClient.GetConferenceDetailsByIdAsync(conferenceId));
            });

            var username               = User.Identity.Name;
            var participantId          = GetIdForParticipantByUsernameInConference(conference, username);
            var conferenceEventRequest = new ConferenceEventRequest
            {
                Conference_id  = conferenceId.ToString(),
                Participant_id = participantId.ToString(),
                Event_id       = Guid.NewGuid().ToString(),
                Event_type     = updateParticipantStatusEventRequest.EventType,
                Time_stamp_utc = DateTime.UtcNow,
                Reason         = EventTypeReasonMapper.Map(updateParticipantStatusEventRequest.EventType)
            };

            var callbackEvent =
                CallbackEventMapper.MapConferenceEventToCallbackEventModel(conferenceEventRequest, conference);
            var handler = _eventHandlerFactory.Get(callbackEvent.EventType);

            try
            {
                await handler.HandleAsync(callbackEvent);
            }
            catch (ConferenceNotFoundException)
            {
                return(BadRequest());
            }

            try
            {
                await _videoApiClient.RaiseVideoEventAsync(conferenceEventRequest);

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#17
0
 public ConferenceControllerTests()
 {
     _loggerMock = new Mock <ILogger <ConferencesController> >();
     _controller = new ConferencesController(_testApiClientMock.Object, _loggerMock.Object);
     _request    = new ConferenceEventRequest()
     {
         ConferenceId  = Guid.NewGuid().ToString(),
         EventId       = Guid.NewGuid().ToString(),
         EventType     = EventsData.EVENT_TYPE,
         ParticipantId = Guid.NewGuid().ToString(),
         Phone         = EventsData.PHONE,
         Reason        = EventsData.REASON,
         TimeStampUtc  = DateTime.UtcNow,
         TransferFrom  = EventsData.TRANSFER_FROM,
         TransferTo    = EventsData.TRANSFER_TO
     };
 }
示例#18
0
        public async Task <IActionResult> UpdateParticipantStatusAsync(Guid conferenceId,
                                                                       UpdateParticipantStatusEventRequest updateParticipantStatusEventRequest)
        {
            var conference = await _conferenceCache.GetOrAddConferenceAsync(conferenceId,
                                                                            () => _videoApiClient.GetConferenceDetailsByIdAsync(conferenceId));

            var participantId          = GetIdForParticipantByUsernameInConference(conference);
            var eventTypeMapper        = _mapperFactory.Get <EventType, string>();
            var conferenceEventRequest = new ConferenceEventRequest
            {
                ConferenceId  = conferenceId.ToString(),
                ParticipantId = participantId.ToString(),
                EventId       = Guid.NewGuid().ToString(),
                EventType     = updateParticipantStatusEventRequest.EventType,
                TimeStampUtc  = DateTime.UtcNow,
                Reason        = eventTypeMapper.Map(updateParticipantStatusEventRequest.EventType)
            };

            var callbackEventMapper = _mapperFactory.Get <ConferenceEventRequest, Conference, CallbackEvent>();
            var callbackEvent       = callbackEventMapper.Map(conferenceEventRequest, conference);
            var handler             = _eventHandlerFactory.Get(callbackEvent.EventType);

            try
            {
                await handler.HandleAsync(callbackEvent);
            }
            catch (ConferenceNotFoundException e)
            {
                _logger.LogError(e, $"Unable to retrieve conference details");
                return(BadRequest(e));
            }

            try
            {
                await _videoApiClient.RaiseVideoEventAsync(conferenceEventRequest);

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                _logger.LogError(e, $"Unable to update participant status for " +
                                 $"participant: {participantId} in conference: {conferenceId}");
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#19
0
        public async Task PostEventAsync_FireEvent(EventType eventType, bool shouldHandleEvent)
        {
            // Arrange
            var conferenceEventRequest = new ConferenceEventRequest
            {
                EventType = eventType
            };

            _mocker.Mock <IEventHandlerFactory>().Setup(x => x.Get(It.IsAny <EventType>())).Returns(_mocker.Mock <IEventHandler>().Object);

            // Act
            await _sut.PostEventAsync(conferenceEventRequest);

            // Assert
            _mocker.Mock <ICommandHandler>().Verify(x => x.Handle(It.IsAny <SaveEventCommand>()), Times.Once);
            _mocker.Mock <IEventHandlerFactory>().Verify(x => x.Get(It.IsAny <EventType>()), shouldHandleEvent ? Times.Once() : Times.Never());
            _mocker.Mock <IEventHandler>().Verify(x => x.HandleAsync(It.IsAny <CallbackEvent>()), shouldHandleEvent ? Times.Once() : Times.Never());
        }
示例#20
0
        public async Task <IActionResult> SendHearingEventAsync(ConferenceEventRequest request)
        {
            try
            {
                var conferenceId = Guid.Parse(request.ConferenceId);
                var conference   = await _conferenceCache.GetOrAddConferenceAsync(conferenceId, () =>
                {
                    _logger.LogTrace("Retrieving conference details for conference: {ConferenceId}", conferenceId);
                    return(_videoApiClient.GetConferenceDetailsByIdAsync(conferenceId));
                });
                await UpdateConferenceRoomParticipants(conference, request);

                var events = new List <ConferenceEventRequest>()
                {
                    request
                };
                if (request.IsParticipantAVmr(conference, out var roomId))
                {
                    request.ParticipantRoomId = roomId.ToString();
                    request.ParticipantId     = null;
                    events = request.CreateEventsForParticipantsInRoom(conference, roomId);
                }

                var callbackEvents = events.Select(e => TransformAndMapRequest(e, conference)).ToList();
                // DO NOT USE Task.WhenAll because the handlers are not thread safe and will overwrite Source<Variable> for each run
                foreach (var e in events)
                {
                    await SendEventToVideoApi(e);
                }

                foreach (var cb in callbackEvents)
                {
                    await PublishEventToUi(cb);
                }

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                _logger.LogError(e, "ConferenceId: {ConferenceId}, ErrorCode: {StatusCode}", request.ConferenceId,
                                 e.StatusCode);
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
        public async Task <IActionResult> PostEventAsync(ConferenceEventRequest request)
        {
            Guid.TryParse(request.ConferenceId, out var conferenceId);
            Guid.TryParse(request.ParticipantId, out var participantId);

            var command = EventRequestMapper.MapEventRequestToEventCommand(conferenceId, request);

            _logger.LogWarning("Handling {ConferenceEventRequest}", nameof(ConferenceEventRequest));

            await _commandHandler.Handle(command);

            if (request.ShouldSkipEventHandler())
            {
                _logger.LogDebug("Handling CallbackEvent skipped due to result of ShouldHandleEvent");
                return(NoContent());
            }

            var callbackEvent = EventRequestMapper.MapEventRequestToEventHandlerDto(conferenceId, participantId, request);
            await _eventHandlerFactory.Get(callbackEvent.EventType).HandleAsync(callbackEvent);

            return(NoContent());
        }
示例#22
0
        public static CallbackEvent MapConferenceEventToCallbackEventModel(ConferenceEventRequest request, Conference conference)
        {
            var eventType    = Enum.Parse <EventType>(request.Event_type.ToString());
            var conferenceId = Guid.Parse(request.Conference_id);

            Guid.TryParse(request.Participant_id, out var participantId);

            var transferFrom = MapRoom(request.Transfer_from.ToString());
            var transferTo   = MapRoom(request.Transfer_to.ToString());

            var callbackEvent = new CallbackEvent
            {
                EventId       = request.Event_id,
                EventType     = eventType,
                ConferenceId  = conferenceId,
                Reason        = request.Reason,
                TransferTo    = transferTo,
                TransferFrom  = transferFrom,
                TimeStampUtc  = request.Time_stamp_utc,
                ParticipantId = participantId
            };

            if (IsEndpointJoined(callbackEvent, conference))
            {
                callbackEvent.EventType = EventType.EndpointJoined;
            }

            if (IsEndpointDisconnected(callbackEvent, conference))
            {
                callbackEvent.EventType = EventType.EndpointDisconnected;
            }

            if (IsEndpointTransferred(callbackEvent, conference))
            {
                callbackEvent.EventType = EventType.EndpointTransfer;
            }

            return(callbackEvent);
        }
        public static CallbackEvent MapEventRequestToEventHandlerDto(Guid conferenceId, Guid participantId,
                                                                     ConferenceEventRequest request)
        {
            GetRoomTypeEnums(request, out var transferTo, out var transferFrom);
            var isValidRoomId = long.TryParse(request.ParticipantRoomId, out var roomId);

            return(new CallbackEvent
            {
                EventId = request.EventId,
                EventType = request.EventType.MapToDomainEnum(),
                ConferenceId = conferenceId,
                Reason = request.Reason,
                TransferTo = transferTo,
                TransferFrom = transferFrom,
                TimeStampUtc = request.TimeStampUtc,
                ParticipantId = participantId,
                Phone = request.Phone,
                TransferredFromRoomLabel = request.TransferFrom,
                TransferredToRoomLabel = request.TransferTo,
                ParticipantRoomId = isValidRoomId ? roomId : (long?)null
            });
        }
        public async Task <IActionResult> SendHearingEventAsync(ConferenceEventRequest request)
        {
            try
            {
                _logger.LogTrace("Received callback from Kinly.");
                _logger.LogTrace($"ConferenceId: {request.Conference_id}, EventType: {request.Event_type}, Participant ID : {request.Participant_id}");

                var conferenceId = Guid.Parse(request.Conference_id);
                var conference   = await _conferenceCache.GetOrAddConferenceAsync(conferenceId, () =>
                {
                    _logger.LogTrace($"Retrieving conference details for conference: ${conferenceId}");
                    return(_videoApiClient.GetConferenceDetailsByIdAsync(conferenceId));
                });

                var callbackEvent = CallbackEventMapper.MapConferenceEventToCallbackEventModel(request, conference);
                request.Event_type = Enum.Parse <VAEventType>(callbackEvent.EventType.ToString());
                if (callbackEvent.EventType != EventType.VhoCall)
                {
                    _logger.LogTrace($"Raising video event: ConferenceId: {request.Conference_id}, EventType: {request.Event_type}");
                    await _videoApiClient.RaiseVideoEventAsync(request);
                }

                if (!string.IsNullOrEmpty(request.Phone))
                {
                    return(NoContent());
                }

                var handler = _eventHandlerFactory.Get(callbackEvent.EventType);
                await handler.HandleAsync(callbackEvent);

                return(NoContent());
            }
            catch (VideoApiException e)
            {
                _logger.LogError(e, $"ConferenceId: {request.Conference_id}, ErrorCode: {e.StatusCode}");
                return(StatusCode(e.StatusCode, e.Response));
            }
        }
示例#25
0
        public async Task <IActionResult> PostEventAsync(ConferenceEventRequest request)
        {
            Guid.TryParse(request.ConferenceId, out var conferenceId);

            var command = new SaveEventCommand(conferenceId, request.EventId, request.EventType,
                                               request.TimeStampUtc, request.TransferFrom, request.TransferTo, request.Reason, request.Phone);

            if (Guid.TryParse(request.ParticipantId, out var participantId))
            {
                command.ParticipantId = participantId;
            }

            _logger.LogWarning("Handling {ConferenceEventRequest}", nameof(ConferenceEventRequest));

            await _commandHandler.Handle(command);

            if (request.ShouldSkipEventHandler())
            {
                _logger.LogDebug("Handling CallbackEvent skipped due to result of ShouldHandleEvent.");
                return(NoContent());
            }

            var callbackEvent = new CallbackEvent
            {
                EventId       = request.EventId,
                EventType     = request.EventType,
                ConferenceId  = conferenceId,
                Reason        = request.Reason,
                TransferTo    = request.TransferTo,
                TransferFrom  = request.TransferFrom,
                TimeStampUtc  = request.TimeStampUtc,
                ParticipantId = participantId,
                Phone         = request.Phone
            };
            await _eventHandlerFactory.Get(request.EventType).HandleAsync(callbackEvent);

            return(NoContent());
        }
示例#26
0
        public static List <ConferenceEventRequest> CreateEventsForParticipantsInRoom(
            this ConferenceEventRequest request,
            Conference conference, long roomId)
        {
            return(conference.CivilianRooms.First(x => x.Id == roomId).Participants.Select(p =>
            {
                var json = JsonConvert.SerializeObject(request);
                var participantEventRequest = JsonConvert.DeserializeObject <ConferenceEventRequest>(json);
                participantEventRequest.ParticipantId = p.ToString();
                participantEventRequest.ParticipantRoomId = roomId.ToString();
                participantEventRequest.EventType = request.EventType switch
                {
                    EventType.Joined when !participantEventRequest.ParticipantRoomId.IsNullOrEmpty() => EventType
                    .RoomParticipantJoined,
                    EventType.Disconnected when !participantEventRequest.ParticipantRoomId.IsNullOrEmpty() => EventType
                    .RoomParticipantDisconnected,
                    EventType.Transfer when !participantEventRequest.ParticipantRoomId.IsNullOrEmpty() => EventType
                    .RoomParticipantTransfer,
                    _ => participantEventRequest.EventType
                };

                return participantEventRequest;
            }).ToList());
        }
        public static SaveEventCommand MapEventRequestToEventCommand(Guid conferenceId, ConferenceEventRequest request)
        {
            GetRoomTypeEnums(request, out var transferTo, out var transferFrom);
            var command = new SaveEventCommand(conferenceId, request.EventId, request.EventType.MapToDomainEnum(),
                                               request.TimeStampUtc, transferFrom, transferTo, request.Reason, request.Phone);

            if (Guid.TryParse(request.ParticipantId, out var participantId))
            {
                command.ParticipantId = participantId;
            }

            command.TransferredFromRoomLabel = request.TransferFrom;
            command.TransferredToRoomLabel   = request.TransferTo;

            if (long.TryParse(request.ParticipantRoomId, out var roomParticipantId))
            {
                command.ParticipantRoomId = roomParticipantId;
            }

            return(command);
        }
示例#28
0
 public static bool IsParticipantAndVmrEvent(this ConferenceEventRequest request)
 {
     return(!request.ParticipantRoomId.IsNullOrEmpty() && !request.ParticipantId.IsNullOrEmpty());
 }
示例#29
0
 public static void Tasks(TaskResponse response, ConferenceEventRequest request)
 {
     response.Should().BeEquivalentTo(request, options => options.ExcludingMissingMembers());
 }