/// <summary> /// Initializes a new instance of the <see cref="RemoteSupportActivityHandler"/> class. /// </summary> /// <param name="microsoftAppCredentials">Microsoft Application credentials for Bot/ME.</param> /// <param name="logger">Sends logs to the Application Insights service.</param> /// <param name="localizer">The current cultures' string localizer.</param> /// <param name="telemetryClient">The Application Insights telemetry client. </param> /// <param name="options">A set of key/value application configuration properties.</param> /// <param name="ticketDetailStorageProvider">Provider to store ticket details to Azure Table Storage.</param> /// <param name="onCallSupportDetailSearchService">Provider to search on call support details in Azure Table Storage.</param> /// <param name="ticketSearchService">Provider to search ticket details in Azure Table Storage.</param> /// <param name="tokenHelper">Generating custom JWT token and retrieving access token for user.</param> /// <param name="cardConfigurationStorageProvider">Provider to search card configuration details in Azure Table Storage.</param> /// <param name="ticketGenerateStorageProvider">Provider to get ticket id to Azure Table Storage.</param> /// <param name="onCallSupportDetailStorageProvider"> Provider for fetching and storing information about on call support in storage table.</param> public RemoteSupportActivityHandler( MicrosoftAppCredentials microsoftAppCredentials, ILogger <RemoteSupportActivityHandler> logger, IStringLocalizer <Strings> localizer, TelemetryClient telemetryClient, IOptions <RemoteSupportActivityHandlerOptions> options, ITicketDetailStorageProvider ticketDetailStorageProvider, IOnCallSupportDetailSearchService onCallSupportDetailSearchService, ITicketSearchService ticketSearchService, ICardConfigurationStorageProvider cardConfigurationStorageProvider, ITokenHelper tokenHelper, ITicketIdGeneratorStorageProvider ticketGenerateStorageProvider, IOnCallSupportDetailStorageProvider onCallSupportDetailStorageProvider) { this.microsoftAppCredentials = microsoftAppCredentials; this.logger = logger; this.localizer = localizer; this.telemetryClient = telemetryClient; this.options = options ?? throw new ArgumentNullException(nameof(options)); this.teamId = this.options.Value.TeamId; this.ticketDetailStorageProvider = ticketDetailStorageProvider; this.ticketSearchService = ticketSearchService; this.onCallSupportDetailSearchService = onCallSupportDetailSearchService; this.appBaseUrl = this.options.Value.AppBaseUri; this.tokenHelper = tokenHelper; this.cardConfigurationStorageProvider = cardConfigurationStorageProvider; this.ticketGenerateStorageProvider = ticketGenerateStorageProvider; this.onCallSupportDetailStorageProvider = onCallSupportDetailStorageProvider; }
/// <summary> /// Initializes a new instance of the <see cref="RemoteSupportController"/> class. /// </summary> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="botAdapter">Remote support bot adapter.</param> /// <param name="microsoftAppCredentials">Microsoft Application credentials for Bot/ME.</param> /// <param name="options">A set of key/value application configuration properties.</param> /// <param name="onCallSupportDetailSearchService">Provider to search on call support details in Azure Table Storage.</param> /// <param name="onCallSupportDetailStorageProvider">Provider to store on call support details in Azure Table Storage.</param> /// <param name="cardConfigurationStorageProvider">Provider to store card configuration details in Azure Table Storage.</param> public RemoteSupportController( ILogger <RemoteSupportController> logger, BotFrameworkAdapter botAdapter, MicrosoftAppCredentials microsoftAppCredentials, IOptions <RemoteSupportActivityHandlerOptions> options, IOnCallSupportDetailSearchService onCallSupportDetailSearchService, IOnCallSupportDetailStorageProvider onCallSupportDetailStorageProvider, ICardConfigurationStorageProvider cardConfigurationStorageProvider) : base() { this.options = options ?? throw new ArgumentNullException(nameof(options)); this.logger = logger; this.botAdapter = botAdapter; this.appId = microsoftAppCredentials != null ? microsoftAppCredentials.MicrosoftAppId : throw new ArgumentNullException(nameof(microsoftAppCredentials)); this.onCallSupportDetailSearchService = onCallSupportDetailSearchService; this.onCallSupportDetailStorageProvider = onCallSupportDetailStorageProvider; this.cardConfigurationStorageProvider = cardConfigurationStorageProvider; }
/// <summary> /// Initializes a new instance of the <see cref="OnCallSupportDetailSearchService"/> class. /// </summary> /// <param name="searchServiceOptions">A set of key/value application configuration properties.</param> /// <param name="storageOptions">A set of key/value application storage configuration properties.</param> /// <param name="onCallSupportDetailStorageProvider">Provider to store on call support details in Azure Table Storage.</param> public OnCallSupportDetailSearchService( IOptionsMonitor <SearchServiceOptions> searchServiceOptions, IOptionsMonitor <StorageOptions> storageOptions, IOnCallSupportDetailStorageProvider onCallSupportDetailStorageProvider) { searchServiceOptions = searchServiceOptions ?? throw new ArgumentNullException(nameof(searchServiceOptions)); storageOptions = storageOptions ?? throw new ArgumentNullException(nameof(storageOptions)); this.searchServiceOptions = searchServiceOptions.CurrentValue; string searchServiceValue = this.searchServiceOptions.SearchServiceName; this.searchServiceClient = new SearchServiceClient( searchServiceValue, new SearchCredentials(this.searchServiceOptions.SearchServiceAdminApiKey)); this.searchIndexClient = new SearchIndexClient( searchServiceValue, OnCallSupportIndexName, new SearchCredentials(this.searchServiceOptions.SearchServiceQueryApiKey)); this.searchIndexingIntervalInMinutes = Convert.ToInt32(this.searchServiceOptions.SearchIndexingIntervalInMinutes, CultureInfo.InvariantCulture); this.onCallSupportDetailStorageProvider = onCallSupportDetailStorageProvider; this.initializeTask = new Lazy <Task>(() => this.InitializeAsync(storageOptions.CurrentValue.ConnectionString)); }
/// <summary> /// Method updates experts card in team after modifying on call experts list. /// </summary> /// <param name="turnContext">Provides context for a turn of a bot.</param> /// <param name="onCallExpertsDetail">Details of on call support experts updated.</param> /// <param name="onCallSupportDetailSearchService">Provider to search on call support details in Azure Table Storage.</param> /// <param name="onCallSupportDetailStorageProvider"> Provider for fetching and storing information about on call support in storage table.</param> /// <param name="localizer">The current cultures' string localizer.</param> /// <returns>A task that sends notification in newly created channel and mention its members.</returns> public static async Task UpdateManageExpertsCardInTeamAsync(ITurnContext <IInvokeActivity> turnContext, OnCallExpertsDetail onCallExpertsDetail, IOnCallSupportDetailSearchService onCallSupportDetailSearchService, IOnCallSupportDetailStorageProvider onCallSupportDetailStorageProvider, IStringLocalizer <Strings> localizer) { // Get last 10 updated on call support data from storage. // This is required because search service refresh interval is 10 minutes. So we need to get latest entry stored in storage from storage provider and append previous 9 updated records to it in order to show on screen. var previousOnCallSupportDetails = await onCallSupportDetailSearchService?.SearchOnCallSupportTeamAsync(string.Empty, 9); var currentOnCallSupportDetails = await onCallSupportDetailStorageProvider?.GetOnCallSupportDetailAsync(onCallExpertsDetail?.OnCallSupportId); List <OnCallSupportDetail> onCallSupportDetails = new List <OnCallSupportDetail> { currentOnCallSupportDetails, }; onCallSupportDetails.AddRange(previousOnCallSupportDetails); // Replace message id in conversation id with card activity id to be refreshed. var conversationId = turnContext?.Activity.Conversation.Id; conversationId = conversationId?.Replace(turnContext.Activity.Conversation.Id.Split(';')[1].Split("=")[1], onCallExpertsDetail?.OnCallSupportCardActivityId, StringComparison.OrdinalIgnoreCase); var onCallSMEDetailCardAttachment = OnCallSMEDetailCard.GetOnCallSMEDetailCard(onCallSupportDetails, localizer); // Add activityId in the data which will be posted to task module in future after clicking on Manage button. AdaptiveCard adaptiveCard = (AdaptiveCard)onCallSMEDetailCardAttachment.Content; AdaptiveCardAction cardAction = (AdaptiveCardAction)((AdaptiveSubmitAction)adaptiveCard?.Actions?[0]).Data; cardAction.ActivityId = onCallExpertsDetail?.OnCallSupportCardActivityId; // Update the card in the SME team with updated on call experts list. var updateExpertsCardActivity = new Activity(ActivityTypes.Message) { Id = onCallExpertsDetail?.OnCallSupportCardActivityId, ReplyToId = onCallExpertsDetail?.OnCallSupportCardActivityId, Conversation = new ConversationAccount { Id = conversationId }, Attachments = new List <Attachment> { onCallSMEDetailCardAttachment }, }; await turnContext.UpdateActivityAsync(updateExpertsCardActivity); }