/// <summary> /// This is the entry point of the service host process. /// </summary> private static void Main() { try { // Log unhandled exceptions. AppDomain.CurrentDomain.UnhandledException += (_, e) => Logger.Error(e.ExceptionObject as Exception, $"Unhandled exception"); TaskScheduler.UnobservedTaskException += (_, e) => Logger.Error(e.Exception, "Unobserved task exception"); // The ServiceManifest.XML file defines one or more service type names. // Registering a service maps a service type name to a .NET type. // When Service Fabric creates an instance of this service type, // an instance of the class is created in this host process. ServiceRuntime.RegisterServiceAsync( "HueBotType", context => new HueBot(context, Logger)).GetAwaiter().GetResult(); ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(HueBot).Name); // Prevents this host process from terminating so services keeps running. Thread.Sleep(Timeout.Infinite); } catch (Exception e) { ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString()); throw; } }
/// <summary> /// add current responder to incident meeting as participant. /// </summary> private void TransferToIncidentMeeting() { Task.Run(async() => { try { var incidentMeetingCallId = statusData?.BotMeetingCallId; var responderStatusData = statusData?.GetResponder(responderId); if (incidentMeetingCallId != null && responderStatusData != null) { var addParticipantRequestData = new AddParticipantRequestData() { ObjectId = responderStatusData.ObjectId, ReplacesCallId = responderStatusData.NotificationCallId, }; await Bot.AddParticipantAsync(incidentMeetingCallId, addParticipantRequestData).ConfigureAwait(false); GraphLogger.Info("Finished to transfer to incident meeting. "); } else { GraphLogger.Warn( $"Tried to transfer to incident meeting but needed info are not valid. Meeting call-id: {incidentMeetingCallId}; status data: {responderStatusData}"); } } catch (Exception ex) { GraphLogger.Error(ex, "Failed to transfer to incident meeting."); throw; } }); }
/// <summary> /// Subscribe to tone. /// </summary> private void SubscribeToTone() { Task.Run(async() => { try { await Call.SubscribeToToneAsync().ConfigureAwait(false); GraphLogger.Info("Started subscribing to tone."); } catch (Exception ex) { GraphLogger.Error(ex, "Failed to subscribe to tone. "); throw; } }); }
/// <summary> /// Play the notification prompt. /// </summary> private void PlayNotificationPrompt() { Task.Run(async() => { try { await Call.PlayPromptAsync(new List <MediaPrompt> { Bot.MediaMap[Bot.NotificationPromptName] }).ConfigureAwait(false); GraphLogger.Info("Started playing notification prompt"); } catch (Exception ex) { GraphLogger.Error(ex, "Failed to play notification prompt."); throw; } }); }
/// <summary> /// Called when recording status flip timer fires. /// </summary> /// <param name="source">The <see cref="ICall" /> source.</param> /// <param name="e">The <see cref="ElapsedEventArgs" /> instance containing the event data.</param> private void OnRecordingStatusFlip(ICall source, ElapsedEventArgs e) { _ = Task.Run(async() => { // TODO: consider rewriting the recording status checking var recordingStatus = new[] { RecordingStatus.Recording, RecordingStatus.NotRecording, RecordingStatus.Failed }; var recordingIndex = this.recordingStatusIndex + 1; if (recordingIndex >= recordingStatus.Length) { var recordedParticipantId = this.Call.Resource.IncomingContext.ObservedParticipantId; var recordedParticipant = this.Call.Participants[recordedParticipantId]; await recordedParticipant.DeleteAsync().ConfigureAwait(false); // Event - Recording has ended _eventPublisher.Publish("CallRecordingFlip", $"Call.Id: {Call.Id} ended"); return; } var newStatus = recordingStatus[recordingIndex]; try { // Event - Log the recording status var status = Enum.GetName(typeof(RecordingStatus), newStatus); _eventPublisher.Publish("CallRecordingFlip", $"Call.Id: {Call.Id} status changed to {status}"); // NOTE: if your implementation supports stopping the recording during the call, you can call the same method above with RecordingStatus.NotRecording await source .UpdateRecordingStatusAsync(newStatus) .ConfigureAwait(false); this.recordingStatusIndex = recordingIndex; } catch (Exception exc) { // e.g. bot joins via direct join - may not have the permissions GraphLogger.Error(exc, $"Failed to flip the recording status to {newStatus}"); // Event - Recording status exception - failed to update _eventPublisher.Publish("CallRecordingFlip", $"Failed to flip the recording status to {newStatus}"); } }).ForgetAndLogExceptionAsync(this.GraphLogger); }
/// <summary> /// Play the notification prompt. /// </summary> private void PlayNotificationPrompt() { Task.Run(async() => { try { var mediaName = endpointId == null ? Bot.BotIncomingPromptName : Bot.BotEndpointIncomingPromptName; await Call.PlayPromptAsync(new List <MediaPrompt> { Bot.MediaMap[mediaName] }).ConfigureAwait(false); GraphLogger.Info("Started playing notification prompt"); } catch (Exception ex) { GraphLogger.Error(ex, "Failed to play notification prompt."); throw; } }); }