Example #1
0
        public static IActionResult RunUploadToQnaMaker(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [Queue("upload-to-qna"), StorageAccount("AzureWebJobsStorage")] ICollector <QnAQueueMessageBatch> msg,
            ILogger log,
            ExecutionContext executionContext)
        {
            log.LogInformation("UploadToQnAMaker Custom Skill: C# HTTP trigger function processed a request.");

            string skillName = executionContext.FunctionName;
            IEnumerable <WebApiRequestRecord> requestRecords = WebApiSkillHelpers.GetRequestRecords(req);

            if (requestRecords == null)
            {
                return(new BadRequestObjectResult($"{skillName} - Invalid request record array."));
            }
            var msgBatch = new QnAQueueMessageBatch();
            WebApiSkillResponse response = WebApiSkillHelpers.ProcessRequestRecords(skillName, requestRecords,
                                                                                    (inRecord, outRecord) =>
            {
                string id          = (inRecord.Data.TryGetValue("id", out object idObject) ? idObject : null) as string;
                string blobName    = (inRecord.Data.TryGetValue("blobName", out object blobNameObject) ? blobNameObject : null) as string;
                string blobUrl     = (inRecord.Data.TryGetValue("blobUrl", out object blobUrlObject) ? blobUrlObject : null) as string;
                string sasToken    = (inRecord.Data.TryGetValue("sasToken", out object sasTokenObject) ? sasTokenObject : null) as string;
                long blobSizeInKBs = (inRecord.Data.TryGetValue("blobSize", out object blobSizeObject) ? (long)blobSizeObject : 0) / 1024;

                if (string.IsNullOrWhiteSpace(blobUrl))
                {
                    outRecord.Errors.Add(new WebApiErrorWarningContract()
                    {
                        Message = $"Parameter '{nameof(blobUrl)}' is required to be present and a valid uri."
                    });
                    return(outRecord);
                }

                string fileUri = WebApiSkillHelpers.CombineSasTokenWithUri(blobUrl, sasToken);

                if (!IsValidFile(blobName, blobSizeInKBs))
                {
                    log.LogError("upload-to-qna-queue-trigger: unable to extract qnas from this file " + blobName + " of size " + blobSizeInKBs);
                    outRecord.Data["status"] = "Failed";
                }
                else
                {
                    var queueMessage = new QnAQueueMessage
                    {
                        Id       = id,
                        FileName = blobName,
                        FileUri  = fileUri
                    };
                    msgBatch.Values.Add(queueMessage);
                    if (msgBatch.Values.Count >= 10)
                    {
                        msg.Add(msgBatch);
                        msgBatch.Values.Clear();
                    }
                    outRecord.Data["status"] = "InQueue";
                }
                return(outRecord);
            });
        public static IActionResult RunDecryptBlobFile(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log,
            ExecutionContext executionContext)
        {
            log.LogInformation("DecryptBlobFile Custom Skill: C# HTTP trigger function processed a request.");

            string skillName = executionContext.FunctionName;
            IEnumerable <WebApiRequestRecord> requestRecords = WebApiSkillHelpers.GetRequestRecords(req);

            if (requestRecords == null)
            {
                return(new BadRequestObjectResult($"{skillName} - Invalid request record array."));
            }

            // Set up access to keyvault to retrieve the key to decrypt the document with
            // Requires that this Azure Function has access via managed identity to the Keyvault where the key is stored.
            var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
            var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
            KeyVaultKeyResolver  cloudResolver = new KeyVaultKeyResolver(kv);
            BlobEncryptionPolicy policy        = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options       = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            WebApiSkillResponse response = WebApiSkillHelpers.ProcessRequestRecords(skillName, requestRecords,
                                                                                    (inRecord, outRecord) =>
            {
                string blobUrl  = (inRecord.Data.TryGetValue("blobUrl", out object blobUrlObject) ? blobUrlObject : null) as string;
                string sasToken = (inRecord.Data.TryGetValue("sasToken", out object sasTokenObject) ? sasTokenObject : null) as string;

                if (string.IsNullOrWhiteSpace(blobUrl))
                {
                    outRecord.Errors.Add(new WebApiErrorWarningContract()
                    {
                        Message = $"Parameter '{nameof(blobUrl)}' is required to be present and a valid uri."
                    });
                    return(outRecord);
                }

                CloudBlockBlob blob = new CloudBlockBlob(new Uri(WebApiSkillHelpers.CombineSasTokenWithUri(blobUrl, sasToken)));
                byte[] decryptedFileData;
                using (var np = new MemoryStream())
                {
                    blob.DownloadToStream(np, null, options, null);
                    decryptedFileData = np.ToArray();
                }
                FileReference decryptedFileReference = new FileReference()
                {
                    data = Convert.ToBase64String(decryptedFileData)
                };
                JObject jObject  = JObject.FromObject(decryptedFileReference);
                jObject["$type"] = "file";
                outRecord.Data["decrypted_file_data"] = jObject;
                return(outRecord);
            });
        public void CanCombineNormalUriWithNormalSasToken()
        {
            // This is typical case when user supplies blob metadata_storage_path and metadata_storage_sas_token
            var uri      = @"http://www.myblob.com";
            var sasToken = @"?sp=rl&st=2020-01-17T23:22:10Z&se=2020-01-31T23:22:00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3D";

            var result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);

            Assert.AreEqual(
                "http://www.myblob.com:80/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);
        }
Example #4
0
        public static async Task <IActionResult> RunAnalyzeForm(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log,
            ExecutionContext executionContext)
        {
            log.LogInformation("Analyze Form Custom Skill: C# HTTP trigger function processed a request.");

            string skillName = executionContext.FunctionName;
            IEnumerable <WebApiRequestRecord> requestRecords = WebApiSkillHelpers.GetRequestRecords(req);

            if (requestRecords == null)
            {
                return(new BadRequestObjectResult($"{skillName} - Invalid request record array."));
            }

            string formsRecognizerEndpointUrl = Environment.GetEnvironmentVariable(formsRecognizerApiEndpointSetting, EnvironmentVariableTarget.Process).TrimEnd('/');
            string formsRecognizerApiKey      = Environment.GetEnvironmentVariable(formsRecognizerApiKeySetting, EnvironmentVariableTarget.Process);


            // string modelId = Environment.GetEnvironmentVariable(modelIdSetting, EnvironmentVariableTarget.Process);

            int retryDelay  = int.TryParse(Environment.GetEnvironmentVariable(retryDelaySetting, EnvironmentVariableTarget.Process), out int parsedRetryDelay) ? parsedRetryDelay : 1000;
            int maxAttempts = int.TryParse(Environment.GetEnvironmentVariable(maxAttemptsSetting, EnvironmentVariableTarget.Process), out int parsedMaxAttempts) ? parsedMaxAttempts : 100;

            Dictionary <string, string> fieldMappings = JsonConvert.DeserializeObject <Dictionary <string, string> >(
                File.ReadAllText($"{executionContext.FunctionAppDirectory}\\field-mappings.json"));

            WebApiSkillResponse response = await WebApiSkillHelpers.ProcessRequestRecordsAsync(skillName, requestRecords,
                                                                                               async (inRecord, outRecord) => {
                var formUrl      = inRecord.Data["formUrl"] as string;
                var formSasToken = inRecord.Data["formSasToken"] as string;
                string formUri   = WebApiSkillHelpers.CombineSasTokenWithUri(formUrl, formSasToken);

                // Create the job
                string jobId = await GetJobId(formsRecognizerEndpointUrl, formUri, formsRecognizerApiKey);

                // Get the results
                for (int attempt = 0; attempt < maxAttempts; attempt++)
                {
                    (string status, JToken result) = await GetJobStatus(jobId, formsRecognizerApiKey);
                    if (status == "failed")
                    {
                        var errors = result.SelectToken("analyzeResult.errors") as JArray;
                        outRecord.Errors.AddRange(errors.Children().Select(error => new WebApiErrorWarningContract
                        {
                            Message = error.SelectToken("message").ToObject <string>()
                        }));
                        return(outRecord);
                    }
                    if (status == "succeeded")
                    {
                        //List<Page> pages = result.SelectToken("analyzeResult.pageResults").ToObject<List<Page>>();


                        List <Page> pages = result.SelectToken("analyzeResult.readResults").ToObject <List <Page> >();


                        foreach (KeyValuePair <string, string> kvp in fieldMappings)
                        {
                            string value = GetField(pages, kvp.Key);
                            if (!string.IsNullOrWhiteSpace(value))
                            {
                                outRecord.Data[kvp.Value] = value;
                            }
                        }
                        return(outRecord);
                    }
                    await Task.Delay(retryDelay);
                }
                outRecord.Errors.Add(new WebApiErrorWarningContract
                {
                    Message = $"The forms recognizer did not finish the job after {maxAttempts} attempts."
                });
                return(outRecord);
            });

            return(new OkObjectResult(response));
        }
        public static async Task <IActionResult> RunSplitImageSkill(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log,
            ExecutionContext executionContext)
        {
            log.LogInformation("Split Image Custom Skill: C# HTTP trigger function processed a request.");

            string skillName = executionContext.FunctionName;
            IEnumerable <WebApiRequestRecord> requestRecords = WebApiSkillHelpers.GetRequestRecords(req);

            if (requestRecords == null)
            {
                return(new BadRequestObjectResult($"{skillName} - Invalid request record array."));
            }

            WebApiSkillResponse response = WebApiSkillHelpers.ProcessRequestRecords(skillName, requestRecords,
                                                                                    (inRecord, outRecord) => {
                var imageUrl = (inRecord.Data.TryGetValue("imageLocation", out object imageUrlObject) ? imageUrlObject : null) as string;
                var sasToken = (inRecord.Data.TryGetValue("imageLocation", out object sasTokenObject) ? sasTokenObject : null) as string;

                if (string.IsNullOrWhiteSpace(imageUrl))
                {
                    outRecord.Errors.Add(new WebApiErrorWarningContract()
                    {
                        Message = $"Parameter '{nameof(imageUrl)}' is required to be present and a valid uri."
                    });
                    return(outRecord);
                }

                JArray splitImages = new JArray();

                using (WebClient client = new WebClient())
                {
                    byte[] fileData = executionContext.FunctionName == "unitTestFunction"
                                            ? fileData = File.ReadAllBytes(imageUrl)                                                                  // this is a unit test, find the file locally
                                            : fileData = client.DownloadData(new Uri(WebApiSkillHelpers.CombineSasTokenWithUri(imageUrl, sasToken))); // download the file from remote server

                    using (var stream = new MemoryStream(fileData))
                    {
                        var originalImage = Image.Load(stream);

                        // chunk the document up into pieces
                        // overlap the chunks to reduce the chances of cutting words in half
                        // (and not being able to OCR that data)
                        for (int x = 0; x < originalImage.Width; x += (MaxImageDimension - ImageOverlapInPixels))
                        {
                            for (int y = 0; y < originalImage.Height; y += (MaxImageDimension - ImageOverlapInPixels))
                            {
                                int startX = x;
                                int endX   = x + MaxImageDimension >= originalImage.Width
                                                ? originalImage.Width
                                                : x + MaxImageDimension;
                                int startY = y;
                                int endY   = y + MaxImageDimension >= originalImage.Height
                                                ? originalImage.Height
                                                : y + MaxImageDimension;

                                var newImageData = CropImage(originalImage, startX, endX, startY, endY);

                                var imageData       = new JObject();
                                imageData["$type"]  = "file";
                                imageData["data"]   = System.Convert.ToBase64String(newImageData);
                                imageData["width"]  = endX - startX;
                                imageData["height"] = endY - startY;
                                splitImages.Add(imageData);
                            }
                        }
                    }
                }

                outRecord.Data["splitImages"] = splitImages;
                return(outRecord);
            });
        public void CanCombineLessWellFormedUriAndSas()
        {
            var uri      = @"www.myblob.com";
            var sasToken = @"?sp=rl&st=2020-01-17T23:22:10Z&se=2020-01-31T23:22:00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3D";

            var result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);

            Assert.AreEqual(
                "http://www.myblob.com:80/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);

            sasToken = @"sp=rl&st=2020-01-17T23:22:10Z&se=2020-01-31T23:22:00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3D";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "http://www.myblob.com:80/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);

            sasToken = @"sp=rl&st=2020-01-17T23:22:10Z";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "http://www.myblob.com:80/?sp=rl&st=2020-01-17T23%3a22%3a10Z"
                , result);

            uri      = @"https://www.myblob.com";
            sasToken = @"?sp=rl&st=2020-01-17T23:22:10Z&se=2020-01-31T23:22:00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3D";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "https://www.myblob.com:443/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);

            uri = @"ftp://www.myblob.net";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "ftp://www.myblob.net:21/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);


            uri = @"http://www.myblob.net:7777";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "http://www.myblob.net:7777/?sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);

            uri = @"http://www.myblob.net:7777?otherUrlParam=value";

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "http://www.myblob.net:7777/?otherUrlParam=value&sp=rl&st=2020-01-17T23%3a22%3a10Z&se=2020-01-31T23%3a22%3a00Z&sv=2019-02-02&sr=b&sig=wcXZOnZGjJssuJYHgjSeSXIrEs6FVckj6lgTtB1VpVc%3d"
                , result);

            uri      = @"http://www.myblob.net";
            sasToken = null; // no sas needed

            result = WebApiSkillHelpers.CombineSasTokenWithUri(uri, sasToken);
            Assert.AreEqual(
                "http://www.myblob.net:80/"
                , result);
        }