diff --git a/CODEOWNERS b/CODEOWNERS index a538cf5..0d9f6e8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,7 +2,7 @@ # Each line is a file pattern followed by one or more owners. # These owners will be the default owners for everything in the repo. -* @subodhjenasymbl +* @subodhjenasymbl @moona3k # Order is important. The last matching pattern has the most precedence. # So if a pull request only touches javascript files, only these owners diff --git a/examples/call-score/cmd.go b/examples/call-score/cmd.go index ee1e99e..a0da389 100644 --- a/examples/call-score/cmd.go +++ b/examples/call-score/cmd.go @@ -1,5 +1,4 @@ // Copyright 2022 Symbl.ai SDK contributors. All Rights Reserved. -// Use of this source code is governed by an Apache-2.0 license that can be found in the LICENSE file. // SPDX-License-Identifier: Apache-2.0 package main @@ -7,112 +6,87 @@ package main import ( "context" "fmt" - "os" + "log" "time" async "github.com/symblai/symbl-go-sdk/pkg/api/async/v1" - interfaces "github.com/symblai/symbl-go-sdk/pkg/api/async/v1/interfaces" symbl "github.com/symblai/symbl-go-sdk/pkg/client" ) +const ( + maxRetries = 20 // Maximum number of retries to check for call score status + retryInterval = time.Minute // Time to wait before next retry + conversationID = "5740965687197696" // A conversation ID + newMediaURL = "https://publicly-accessible-audio-url.mp3" // New media URL for updating insights details +) + func main() { + // Initialize the Symbl client symbl.Init(symbl.SybmlInit{ LogLevel: symbl.LogLevelTrace, }) ctx := context.Background() + // Create a new REST client restClient, err := symbl.NewRestClient(ctx) - if err == nil { - fmt.Println("Succeeded!\n\n") - } else { - fmt.Printf("New failed. Err: %v\n", err) - os.Exit(1) + if err != nil { + log.Fatalf("Failed to create REST client. Error: %v\n", err) } + fmt.Println("REST client created successfully.") asyncClient := async.New(restClient) - ufRequest := interfaces.AsyncURLFileRequest{ - DetectEntities: true, - EnableSpeakerDiarization: true, - DiarizationSpeakerCount: 2, - ParentRefs: true, - Sentiment: true, - Mode: "default", - Features: interfaces.Features{ - FeatureList: []string{"insights", "callScore"}, - }, - ConversationType: "sales", - Metadata: interfaces.Metadata{ - SalesStage: "general", - ProspectName: "John Doe", - }, - } - // Process Call Score - conversationJob, err := asyncClient.PostFileWithOptions(ctx, "newPhonecall.mp3", ufRequest) - if err == nil { - fmt.Printf("JobID: %s, ConversationID: %s\n\n", conversationJob.JobID, conversationJob.ConversationID) - } else { - fmt.Printf("PostFile failed. Err: %v\n", err) - os.Exit(1) - } - - // Wait for Processing (Wait for 20 minutes, increase if needed) - for i := 0; i < 20; i++ { - result, err := asyncClient.GetCallScoreStatusById(ctx, conversationJob.ConversationID) - fmt.Printf("Current status (attempt %d): %s", i+1, result.Status) + // Check the status of CallScore and wait until it's completed + waitForCallScoreCompletion(ctx, asyncClient) - if err == nil && result.Status == "completed" { - break - } + // Subsequent operations and their respective log messages + performAsyncClientOperations(ctx, asyncClient) +} +// waitForCallScoreCompletion waits for the CallScoreStatus to be completed, retrying for defined times and interval. +func waitForCallScoreCompletion(ctx context.Context, asyncClient *async.Client) { + for attempt := 1; attempt <= maxRetries; attempt++ { + result, err := asyncClient.GetCallScoreStatusById(ctx, conversationID) if err != nil { - fmt.Printf("Error fetching status (attempt %d): %v", i+1, err) + log.Printf("Error fetching status (attempt %d): %v\n", attempt, err) + } else { + fmt.Printf("Current status (attempt %d): %s\n", attempt, result.Status) + if result.Status == "completed" { + fmt.Println("CallScoreStatus is completed!") + return + } } - - // hardcoded retryDelay - time.Sleep(time.Minute) + time.Sleep(retryInterval) } + log.Println("CallScoreStatus did not complete within the maximum retry limit.") +} - // Fetch the CallScore - callScore, err := asyncClient.GetCallScore(ctx, conversationJob.ConversationID) - if err == nil { - fmt.Printf("Call Score: %v\n", callScore) +// performAsyncClientOperations performs various operations using the asyncClient and logs their outcomes. +func performAsyncClientOperations(ctx context.Context, asyncClient *async.Client) { + if callScore, err := asyncClient.GetCallScore(ctx, conversationID); err != nil { + log.Printf("Fetch Call Score failed. Error: %v\n", err) } else { - fmt.Printf("Fetch Call Score failed. Err: %v\n", err) - // os.Exit(1) + fmt.Printf("Call Score: %v\n", callScore) } - // Fetch Insights List UI URL - insightsListURL, err := asyncClient.GetInsightsListUiURI(ctx) - if err == nil { - fmt.Printf("Insights List URL: %s\n", insightsListURL) + if insightsListURL, err := asyncClient.GetInsightsListUiURI(ctx); err != nil { + log.Printf("Fetch Insights List URL failed. Error: %v\n", err) } else { - fmt.Printf("Fetch Insights List URL failed. Err: %v\n", err) - // os.Exit(1) + fmt.Printf("Insights List URL: %s\n", insightsListURL) } - // Fetch Insights Details UI URL - insightsDetailsURL, err := asyncClient.GetInsightsDetailsUiURI(ctx, conversationJob.ConversationID) - if err == nil { - fmt.Printf("Insights Details URL: %s\n", insightsDetailsURL) + if insightsDetailsURL, err := asyncClient.GetInsightsDetailsUiURI(ctx, conversationID); err != nil { + log.Printf("Fetch Insights Details URL failed. Error: %v\n", err) } else { - fmt.Printf("Fetch Insights Details URL failed. Err: %v\n", err) - // os.Exit(1) + fmt.Printf("Insights Details URL: %s\n", insightsDetailsURL) } - // Update Media URL for Insights Details UI - newMediaUrl := "https://publicly-accessible-audio-url.mp3" - err = asyncClient.UpdateMediaUrlForInsightsDetailsUI(ctx, conversationJob.ConversationID, newMediaUrl) - if err == nil { - fmt.Printf("Media URL for Insights Details UI updated successfully.\n") + if err := asyncClient.UpdateMediaUrlForInsightsDetailsUI(ctx, conversationID, newMediaURL); err != nil { + log.Printf("Update Media URL for Insights Details UI failed. Error: %v\n", err) } else { - fmt.Printf("Update Media URL for Insights Details UI failed. Err: %v\n", err) - // os.Exit(1) + fmt.Println("Media URL for Insights Details UI updated successfully.") } - fmt.Printf("\n\n") - fmt.Printf("\n\n") - - fmt.Printf("Succeeded") + fmt.Println("Operations Completed Successfully.") } diff --git a/pkg/api/async/v1/summaryui.go b/pkg/api/async/v1/summaryui.go index d02ac21..077bb2c 100644 --- a/pkg/api/async/v1/summaryui.go +++ b/pkg/api/async/v1/summaryui.go @@ -357,61 +357,42 @@ func (c *Client) GetInsightsDetailsUiURI(ctx context.Context, conversationId str // UpdateMediaUrlForInsightsDetailsUI updates the audio/video URL that will be played in Insights UI func (c *Client) UpdateMediaUrlForInsightsDetailsUI(ctx context.Context, conversationId string, mediaUrl string) error { - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI ENTER\n") - - // checks - if ctx == nil { - ctx = context.Background() - } - if conversationId == "" { - klog.V(1).Infof("conversationId is empty\n") - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return ErrInvalidInput - } - if mediaUrl == "" { - klog.V(1).Infof("mediaUrl is empty\n") - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return ErrInvalidInput - } - - // request - URI := fmt.Sprintf("%s%s", - version.GetAsyncAPI(version.UpdateMediaURI, conversationId), // You'll need to define the endpoint in your version package - c.getQueryParamFromContext(ctx)) - klog.V(6).Infof("Calling %s\n", URI) - - requestBody, err := json.Marshal(map[string]string{ - "url": mediaUrl, - }) - if err != nil { - klog.V(1).Infof("json.Marshal failed. Err: %v\n", err) - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return err - } - - req, err := http.NewRequestWithContext(ctx, "PUT", URI, bytes.NewBuffer(requestBody)) - if err != nil { - klog.V(1).Infof("http.NewRequestWithContext failed. Err: %v\n", err) - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return err - } - - // execute request - resp, err := c.Client.Do(req) - if err != nil { - klog.V(1).Infof("Request execution failed. Err: %v\n", err) - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - klog.V(1).Infof("HTTP Code: %v\n", resp.StatusCode) - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return fmt.Errorf("HTTP Code: %v", resp.StatusCode) - } - - klog.V(3).Infof("Update MediaUrl For InsightsUI succeeded\n") - klog.V(6).Infof("async.UpdateMediaUrlForInsightsDetailsUI LEAVE\n") - return nil + klog.V(6).Info("async.UpdateMediaUrlForInsightsDetailsUI ENTER") + defer klog.V(6).Info("async.UpdateMediaUrlForInsightsDetailsUI LEAVE") + + // checks + if conversationId == "" || mediaUrl == "" { + klog.V(1).Info("conversationId or mediaUrl is empty") + return ErrInvalidInput + } + + // request + URI := fmt.Sprintf("%s%s", + version.GetAsyncAPI(version.UpdateMediaURI, conversationId), + c.getQueryParamFromContext(ctx)) + klog.V(6).Infof("Calling %s", URI) + + requestBody, err := json.Marshal(map[string]string{ + "url": mediaUrl, + }) + if err != nil { + klog.V(1).Infof("json.Marshal failed. Err: %v", err) + return err + } + + req, err := http.NewRequestWithContext(ctx, "PUT", URI, bytes.NewBuffer(requestBody)) + if err != nil { + klog.V(1).Infof("http.NewRequestWithContext failed. Err: %v", err) + return err + } + + // execute request + err = c.Do(ctx, req, nil) // we don't need the response body + if err != nil { + klog.V(1).Infof("Request execution failed. Err: %v", err) + return err + } + + klog.V(3).Info("Update MediaUrl For InsightsUI succeeded") + return nil } diff --git a/pkg/api/version/async-version.go b/pkg/api/version/async-version.go index 4c5b540..51e9e69 100644 --- a/pkg/api/version/async-version.go +++ b/pkg/api/version/async-version.go @@ -52,7 +52,7 @@ const ( // Insights Ui InsightsListUiURI string = "https://api.symbl.ai/%s/conversations/experiences/insights/list?includeCallScore=true" InsightsDetailsUiURI string = "https://api.symbl.ai/%s/conversations/experiences/insights/details/%s?includeCallScore=true" - UpdateMediaURI string = "https://api.symbl.ai/%s/conversations/%s/experience/url" + UpdateMediaURI string = "https://api.symbl.ai/%s/conversations/%s/experiences/url" // Conversations ConversationsURI string = "https://api.symbl.ai/%s/conversations"