├── .gitignore ├── CONTRIBUTING.md ├── ContentModeratorSDK.Tests ├── App.config ├── Content │ ├── img_300.jpg │ └── sample.jpg ├── ContentModeratorSDK.Test.csproj ├── ImageListAndMatchScenarios.cs ├── ModeratorTests.cs ├── Properties │ └── AssemblyInfo.cs ├── ReviewTests.cs ├── TextListScreenScenarios.cs ├── data.xlsx └── packages.config ├── ContentModeratorSDK.sln ├── ContentModeratorSDK ├── ClientBase.cs ├── ClientError.cs ├── ClientException.cs ├── Constants.cs ├── ContentModeratorSDK.csproj ├── Contract │ ├── Image │ │ ├── AdvancedInfo.cs │ │ ├── DataRepresentation.cs │ │ ├── DetectFacesResult.cs │ │ ├── EvaluateImageResult.cs │ │ ├── ImageAddResult.cs │ │ ├── ImageListResult.cs │ │ ├── ImageRefreshIndexResult.cs │ │ ├── ImageResult.cs │ │ ├── KeyValue.cs │ │ ├── MatchResult.cs │ │ ├── OCRImageResult.cs │ │ └── Result.cs │ ├── ListItemResult.cs │ ├── Review │ │ ├── CreateJobResult.cs │ │ ├── JobDetailsResult.cs │ │ ├── KeyValue.cs │ │ ├── ReviewRequest.cs │ │ ├── ReviewResponse.cs │ │ ├── TokenResult.cs │ │ └── WorkFlowItem.cs │ ├── Status.cs │ └── Text │ │ ├── IdentifyLanguageResult.cs │ │ ├── MatchDetails.cs │ │ ├── MatchTerm.cs │ │ ├── Pii.cs │ │ ├── Result.cs │ │ ├── ScreenTextResult.cs │ │ └── TermGetAllResult.cs ├── IListManagementClient.cs ├── IModeratorClient.cs ├── IReviewClient.cs ├── ListManagementClient.cs ├── ModeratorClient.cs ├── ModeratorHelper.cs ├── Properties │ └── AssemblyInfo.cs ├── ReviewClient.cs ├── nugetpackager │ ├── NuGet.exe │ ├── Package.nuspec │ └── PostBuildCommand.bat └── packages.config ├── LICENSE-IMAGE.md ├── LICENSE.md ├── README.md └── ThirdPartyNotices.txt /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Microsoft Cognitive Services Client Libraries & Samples 2 | =============================================== 3 | So, you want to contribute on a client library or sample for one of the Microsoft Cognitive Services. 4 | Here's what you need to know. 5 | 6 | 1. Each SDK should include both a client library and a sample showing the API in 7 | action 8 | 9 | 2. When working on an SDK, it's important that we are consistent from project to project, so we ask you to follow the coding guidelines below: 10 | 11 | - Windows [(Coding guidelines for C#)](https://msdn.microsoft.com/en-us/library/ff926074.aspx) -- also reference our [common Windows code](https://github.com/Microsoft/Cognitive-common-windows) for building samples 12 | 13 | - Android [(Coding guidelines for 14 | Java)]() 15 | 16 | - iOS Objective-C [(Coding guidelines for 17 | Cocoa)]() 18 | 19 | - Optional: Client Javascript ([Coding guidelines for 20 | npm]()) 21 | 22 | 3. Samples are important for illustrating how to actually call into the API. 23 | Samples should be as visual and reusable as possible. 24 | 25 | - Do: 26 | 27 | - Create a UI sample when possible. 28 | 29 | - Make your sample user friendly. Expect that developers will want to try 30 | different mainline scenarios and key APIs. 31 | 32 | - Create code that's easy for other developers to copy/paste into their 33 | own solutions 34 | 35 | - Consider: 36 | 37 | - Adding UI to allow devs to quickly copy/paste subscription keys, instead 38 | of updating them in the code or using a config file. The 39 | FaceAPI-WPF-Samples.sln provides an example. 40 | 41 | - Don't: 42 | 43 | - Leave your subscription key in the source of samples. You do not want your key to be abused by others. 44 | 45 | Happy coding! 46 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/Content/img_300.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftContentModerator/Microsoft.CognitiveServices.ContentModerator-Windows/38236497d16cb6020b55b91419610316adb9e49a/ContentModeratorSDK.Tests/Content/img_300.jpg -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/Content/sample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftContentModerator/Microsoft.CognitiveServices.ContentModerator-Windows/38236497d16cb6020b55b91419610316adb9e49a/ContentModeratorSDK.Tests/Content/sample.jpg -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/ContentModeratorSDK.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2} 7 | Library 8 | Properties 9 | ContentModeratorSDK.Test 10 | ContentModeratorSDK.Test 11 | v4.5.2 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | SAK 20 | SAK 21 | SAK 22 | SAK 23 | 24 | 25 | true 26 | full 27 | false 28 | bin\Debug\ 29 | DEBUG;TRACE 30 | prompt 31 | 4 32 | AnyCPU 33 | 34 | 35 | pdbonly 36 | true 37 | bin\Release\ 38 | TRACE 39 | prompt 40 | 4 41 | 42 | 43 | true 44 | bin\x64\Debug\ 45 | DEBUG;TRACE 46 | full 47 | x64 48 | prompt 49 | MinimumRecommendedRules.ruleset 50 | 51 | 52 | bin\x64\Release\ 53 | TRACE 54 | true 55 | pdbonly 56 | x64 57 | prompt 58 | MinimumRecommendedRules.ruleset 59 | 60 | 61 | 62 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 63 | True 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | False 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | {961284a5-1e23-416b-aba0-ff28c2327cab} 94 | ContentModeratorSDK 95 | 96 | 97 | 98 | 99 | Designer 100 | 101 | 102 | Always 103 | 104 | 105 | 106 | 107 | 108 | Always 109 | 110 | 111 | Always 112 | 113 | 114 | 115 | 116 | 117 | 118 | False 119 | 120 | 121 | False 122 | 123 | 124 | False 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | 133 | 134 | 141 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/ImageListAndMatchScenarios.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace ContentModeratorSDK.Test 5 | { 6 | using System.Collections.Generic; 7 | using System.Configuration; 8 | using System.Linq; 9 | using System.Runtime.CompilerServices; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | using Microsoft.CognitiveServices.ContentModerator; 13 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 14 | 15 | [TestClass] 16 | public class ImageListAndMatchScenarios 17 | { 18 | private static string listId = ""; 19 | 20 | private readonly ListManagementClient imageListclient = null; 21 | private readonly ModeratorClient moderatorClient = null; 22 | public ImageListAndMatchScenarios() 23 | { 24 | this.imageListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 25 | this.moderatorClient = new ModeratorClient(ConfigurationManager.AppSettings["subscriptionkey"]); 26 | } 27 | 28 | /// 29 | ///Gets or sets the test context which provides 30 | ///information about and functionality for the current test run. 31 | /// 32 | public TestContext TestContext { get; set; } 33 | 34 | [ClassInitialize()] 35 | public static void ClassInitialize(TestContext testContext) 36 | { 37 | //Create a new list 38 | //Get all Lists to verify creation 39 | 40 | var imageListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 41 | var listName = Guid.NewGuid().ToString("n"); 42 | 43 | Dictionary listMetaData = new Dictionary(); 44 | listMetaData.Add("MyListMData1", "MyListMData1"); 45 | listMetaData.Add("MyListMData2", "MyListMData2"); 46 | 47 | var createRes = imageListclient.ImageListCreateAsync(listName, "This is Unit Test", listMetaData).Result; 48 | Assert.IsNotNull(createRes); 49 | Assert.IsTrue(!string.IsNullOrWhiteSpace(createRes.Id)); 50 | 51 | listId = createRes.Id; 52 | 53 | var getAllRes = imageListclient.ImageListGetAllAsync().Result; 54 | Assert.IsNotNull(getAllRes); 55 | Assert.IsTrue(getAllRes.Count > 0); 56 | Assert.IsTrue(getAllRes.Exists(e => e.Id == createRes.Id)); 57 | 58 | Dictionary x = new Dictionary(); 59 | 60 | 61 | 62 | } 63 | 64 | [ClassCleanup()] 65 | public static void ClassCleanup() 66 | { 67 | //Delete ALL Images 68 | //Delete Image List 69 | //Call get all lists to verify deletion 70 | 71 | var imageListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 72 | 73 | var updateImageList = imageListclient.ImageListUpdateAsync(listId, "Updated Name", "Updated", null).Result; 74 | Assert.IsNotNull(updateImageList); 75 | 76 | var deleteAllRes = imageListclient.ImageDeleteAllAsync(listId).Result; 77 | Assert.IsNotNull(deleteAllRes); 78 | 79 | var deleteImageList = imageListclient.ImageListDeleteAsync(listId).Result; 80 | Assert.IsNotNull(deleteImageList); 81 | 82 | 83 | var getAllRes = imageListclient.ImageListGetAllAsync().Result; 84 | Assert.IsNotNull(getAllRes); 85 | Assert.IsTrue(!getAllRes.Exists(e => e.Id == listId)); 86 | } 87 | 88 | #region Additional test attributes 89 | // 90 | // You can use the following additional attributes as you write your tests: 91 | // 92 | // Use ClassInitialize to run code before running the first test in the class 93 | 94 | // 95 | // Use ClassCleanup to run code after all tests in a class have run 96 | // [ClassCleanup()] 97 | // public static void MyClassCleanup() { } 98 | // 99 | // Use TestInitialize to run code before running each test 100 | // [TestInitialize()] 101 | // public void MyTestInitialize() { } 102 | // 103 | // Use TestCleanup to run code after each test has run 104 | // [TestCleanup()] 105 | // public void MyTestCleanup() { } 106 | // 107 | #endregion 108 | 109 | 110 | [TestMethod] 111 | [TestCategory("Data Driven")] 112 | [DataSource("ImageMatch")] 113 | public async Task ImageMatchTestsAsync() 114 | { 115 | 116 | //Add Image 117 | //Refresh Index 118 | //List all images 119 | //Call Match - Should Match 120 | //Delete Image 121 | //List all images 122 | //Refresh Index 123 | //Call Match - Should not Match 124 | 125 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 126 | var expectSizeException = bool.Parse(this.TestContext.DataRow["SizeException"].ToString()); 127 | if (!isEnabled) 128 | { 129 | return; 130 | } 131 | 132 | 133 | Thread.Sleep(1000); 134 | 135 | var imageUrl = this.TestContext.DataRow["DataVal"].ToString(); 136 | var imageTags = this.TestContext.DataRow["Tag"].ToString(); 137 | var imageLabel = this.TestContext.DataRow["Label"].ToString(); 138 | 139 | try 140 | { 141 | var addImageRes = 142 | await 143 | this.imageListclient.ImageAddAsync( 144 | imageUrl, 145 | DataRepresentationType.Url, 146 | listId, 147 | imageTags, 148 | imageLabel); 149 | 150 | 151 | 152 | Assert.IsNotNull(addImageRes); 153 | Assert.IsTrue(!string.IsNullOrWhiteSpace(addImageRes.ContentId)); 154 | 155 | var refreshIndexRes = await this.imageListclient.ImageListRefreshIndexAsync(listId); 156 | Assert.IsNotNull(refreshIndexRes); 157 | Thread.Sleep(10000); 158 | 159 | 160 | var listAllImagesRes = await this.imageListclient.ImageGetAllIdsAsync(listId); 161 | Assert.IsNotNull(listAllImagesRes); 162 | Assert.IsTrue(listAllImagesRes.ContentIds.Exists(e => e.ToString() == addImageRes.ContentId)); 163 | 164 | 165 | var matchRes = 166 | await this.moderatorClient.MatchImageAsync(imageUrl, DataRepresentationType.Url, false, listId); 167 | Assert.IsNotNull(matchRes); 168 | Assert.IsTrue(matchRes.Matches.Exists(m => m.MatchId.ToString() == addImageRes.ContentId)); 169 | 170 | var deleteImageRes = await this.imageListclient.ImageDeleteAsync(listId, addImageRes.ContentId); 171 | Assert.IsNotNull(deleteImageRes); 172 | 173 | var listAllAfterDeleteImagesRes = await this.imageListclient.ImageGetAllIdsAsync(listId); 174 | Assert.IsNotNull(listAllAfterDeleteImagesRes); 175 | Assert.IsTrue( 176 | !listAllAfterDeleteImagesRes.ContentIds.Exists(e => e.ToString() == addImageRes.ContentId)); 177 | 178 | var refreshIndexAfterDeleteRes = await this.imageListclient.ImageListRefreshIndexAsync(listId); 179 | Assert.IsNotNull(refreshIndexRes); 180 | Thread.Sleep(10000); 181 | 182 | var matchAfterDeleteRes = 183 | await this.moderatorClient.MatchImageAsync(imageUrl, DataRepresentationType.Url, false, listId); 184 | Assert.IsNotNull(matchAfterDeleteRes); 185 | Assert.IsTrue(!matchAfterDeleteRes.Matches.Exists(m => m.MatchId.ToString() == addImageRes.ContentId)); 186 | 187 | if(expectSizeException) 188 | { 189 | Assert.Fail("Image Size Expection was expected!!"); 190 | } 191 | 192 | } 193 | catch (Microsoft.CognitiveServices.ContentModerator.ClientException ex) 194 | { 195 | 196 | if((ex.Error.Message != "Image Size Error") || !expectSizeException) 197 | { 198 | throw; 199 | } 200 | } 201 | 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/ModeratorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using Microsoft.CognitiveServices.ContentModerator; 6 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | using Newtonsoft.Json; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting.Web; 10 | 11 | namespace ContentModeratorSDK.Test 12 | { 13 | using System.Configuration; 14 | using System.Diagnostics; 15 | using System.Net; 16 | using System.Threading.Tasks; 17 | 18 | /// 19 | /// Summary description for ImageTests 20 | /// 21 | [TestClass] 22 | public class ModeratorTests 23 | { 24 | private readonly ModeratorClient client = null; 25 | private readonly string testImageContent = @"Content\sample.jpg"; 26 | private readonly string testImageContentUrl = @"https://hashblobsm2.blob.core.windows.net/testimages/PNGOCR.png"; 27 | private readonly string matchImageContent = @"Content\img_300.jpg"; 28 | private readonly string matchImageContentUrl = @"https://moderatorsampleimages.blob.core.windows.net/samples/img_300.jpg"; 29 | 30 | private readonly string defaultLanguage = "eng"; 31 | private readonly bool isCache = false; 32 | private readonly string listId = "Your List Id"; 33 | public ModeratorTests() 34 | { 35 | this.client = new ModeratorClient(ConfigurationManager.AppSettings["subscriptionkey"]); 36 | 37 | } 38 | 39 | /// 40 | ///Gets or sets the test context which provides 41 | ///information about and functionality for the current test run. 42 | /// 43 | public TestContext TestContext { get; set; } 44 | 45 | [TestMethod()] 46 | [DataSource("ImageEvalute")] 47 | [TestCategory("Data Driven")] 48 | public async Task EvaluateImageTestDataBasedAsync() 49 | { 50 | string type = this.TestContext.DataRow["DataType"].ToString(); 51 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 52 | var expectSizeException = bool.Parse(this.TestContext.DataRow["SizeException"].ToString()); 53 | 54 | 55 | if (!isEnabled) 56 | { 57 | return; 58 | } 59 | 60 | EvaluateImageResult result = null; 61 | 62 | try 63 | { 64 | this.TestContext.WriteLine("ImageEvaluate - Running Data Row"); 65 | switch (type) 66 | { 67 | case "url": 68 | { 69 | result = 70 | await 71 | this.client.EvaluateImageAsync( 72 | this.TestContext.DataRow["DataVal"].ToString(), 73 | DataRepresentationType.Url, 74 | bool.Parse(this.TestContext.DataRow["Cache"].ToString())); 75 | break; 76 | } 77 | case "raw": 78 | { 79 | var webClient = new WebClient(); 80 | byte[] imageBytes = webClient.DownloadData(this.TestContext.DataRow["DataVal"].ToString()); 81 | 82 | result = 83 | await 84 | this.client.EvaluateImageAsync( 85 | new MemoryStream(imageBytes), 86 | bool.Parse(this.TestContext.DataRow["Cache"].ToString())); 87 | break; 88 | } 89 | } 90 | 91 | if(expectSizeException) 92 | { 93 | Assert.Fail("Image Size Expection was expected!!"); 94 | } 95 | 96 | 97 | Assert.IsNotNull(result); 98 | 99 | if (bool.Parse(this.TestContext.DataRow["Cache"].ToString())) 100 | { 101 | Assert.IsTrue(!string.IsNullOrWhiteSpace(result.CacheID), "Expected CacheId, Response: {0}", JsonConvert.SerializeObject(result)); 102 | } 103 | else 104 | { 105 | Assert.IsTrue(string.IsNullOrWhiteSpace(result.CacheID), "CacheId NOT EXPECTED, Response: {0}", JsonConvert.SerializeObject(result)); 106 | } 107 | 108 | 109 | Assert.IsTrue(result.AdultClassificationScore > 0, "Expected higher than 0 Adult Classification Score value for test image, Response: {0}", JsonConvert.SerializeObject(result)); 110 | Assert.IsTrue(result.RacyClassificationScore > 0, "Expected higher than 0 Racy Classification Score value for test image, Response: {0}", JsonConvert.SerializeObject(result)); 111 | Assert.AreEqual(result.IsImageAdultClassified, bool.Parse(this.TestContext.DataRow["IsAdult"].ToString()), "Image should not have been classified as Adult, Response: {0}", JsonConvert.SerializeObject(result)); 112 | Assert.AreEqual(result.IsImageRacyClassified, bool.Parse(this.TestContext.DataRow["IsRacy"].ToString()), "Image should not have been classified as Racy, Response: {0}", JsonConvert.SerializeObject(result)); 113 | 114 | } 115 | catch (Microsoft.CognitiveServices.ContentModerator.ClientException ex) 116 | { 117 | if((ex.Error.Message != "Image Size Error") || !expectSizeException) 118 | { 119 | throw; 120 | } 121 | } 122 | } 123 | 124 | [TestMethod()] 125 | [DataSource("DetectFaces")] 126 | [TestCategory("Data Driven")] 127 | 128 | public async Task DetectFacesTestDataBasedAsync() 129 | { 130 | string type = this.TestContext.DataRow["DataType"].ToString(); 131 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 132 | var expectSizeException = bool.Parse(this.TestContext.DataRow["SizeException"].ToString()); 133 | 134 | if (!isEnabled) 135 | { 136 | return; 137 | } 138 | 139 | DetectFacesResult result = null; 140 | 141 | try 142 | { 143 | switch (type) 144 | { 145 | case "url": 146 | { 147 | result = 148 | await 149 | this.client.DetectFacesImageAsync( 150 | this.TestContext.DataRow["DataVal"].ToString(), 151 | DataRepresentationType.Url, 152 | bool.Parse(this.TestContext.DataRow["Cache"].ToString())); 153 | break; 154 | } 155 | case "raw": 156 | { 157 | var webClient = new WebClient(); 158 | byte[] imageBytes = webClient.DownloadData(this.TestContext.DataRow["DataVal"].ToString()); 159 | 160 | result = 161 | await 162 | this.client.DetectFacesImageAsync( 163 | new MemoryStream(imageBytes), 164 | bool.Parse(this.TestContext.DataRow["Cache"].ToString())); 165 | break; 166 | } 167 | } 168 | 169 | 170 | if(expectSizeException) 171 | { 172 | Assert.Fail("Image Size Expection was expected!!"); 173 | } 174 | Assert.IsNotNull(result); 175 | if (bool.Parse(this.TestContext.DataRow["Cache"].ToString())) 176 | { 177 | Assert.IsTrue(!string.IsNullOrWhiteSpace(result.CacheID), "Expected CacheId, Response: {0}", JsonConvert.SerializeObject(result)); 178 | } 179 | else 180 | { 181 | Assert.IsTrue(string.IsNullOrWhiteSpace(result.CacheID), "CacheId NOT EXPECTED, Response: {0}", JsonConvert.SerializeObject(result)); 182 | } 183 | 184 | var expectedFaceCount = int.Parse(this.TestContext.DataRow["FaceCount"].ToString()); 185 | Assert.IsTrue(result.Count == expectedFaceCount, "Face count is less than 1, Response: {0}", JsonConvert.SerializeObject(result)); 186 | 187 | if (expectedFaceCount > 0) 188 | { 189 | Assert.IsNotNull( 190 | result.Faces, 191 | "No Faces detected, Response: {0}", 192 | JsonConvert.SerializeObject(result)); 193 | Assert.IsTrue( 194 | result.Faces.Length > 0, 195 | "No Faces detected, Response: {0}", 196 | JsonConvert.SerializeObject(result)); 197 | } 198 | else 199 | { 200 | Assert.IsTrue( 201 | result.Faces == null || result.Faces.Length == 0, 202 | "Faces array should be empty: {0}", 203 | JsonConvert.SerializeObject(result)); 204 | } 205 | } 206 | catch (Microsoft.CognitiveServices.ContentModerator.ClientException ex) 207 | { 208 | 209 | if((ex.Error.Message != "Image Size Error") || !expectSizeException) 210 | { 211 | throw; 212 | } 213 | } 214 | } 215 | 216 | [TestMethod()] 217 | [DataSource("OCRImage")] 218 | [TestCategory("Data Driven")] 219 | public async Task OCRImageTestDataBasedAsync() 220 | { 221 | string type = this.TestContext.DataRow["DataType"].ToString(); 222 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 223 | var expectSizeException = bool.Parse(this.TestContext.DataRow["SizeException"].ToString()); 224 | var expectUnknownException = bool.Parse(this.TestContext.DataRow["UnknownException"].ToString()); 225 | 226 | if (!isEnabled) 227 | { 228 | return; 229 | } 230 | 231 | OcrImageResult result = null; 232 | 233 | try 234 | { 235 | this.TestContext.WriteLine("OCRIMAGE - Running Data Row"); 236 | switch (type) 237 | { 238 | case "url": 239 | { 240 | result = 241 | await 242 | this.client.OCRImageAsync( 243 | this.TestContext.DataRow["DataVal"].ToString(), 244 | DataRepresentationType.Url, 245 | bool.Parse(this.TestContext.DataRow["Cache"].ToString()), 246 | bool.Parse(this.TestContext.DataRow["Enhanced"].ToString()), 247 | this.TestContext.DataRow["Language"].ToString()); 248 | break; 249 | } 250 | case "raw": 251 | { 252 | var webClient = new WebClient(); 253 | byte[] imageBytes = webClient.DownloadData(this.TestContext.DataRow["DataVal"].ToString()); 254 | 255 | result = 256 | await 257 | this.client.OCRImageAsync( 258 | new MemoryStream(imageBytes), 259 | bool.Parse(this.TestContext.DataRow["Cache"].ToString()), 260 | bool.Parse(this.TestContext.DataRow["Enhanced"].ToString()), 261 | this.TestContext.DataRow["Language"].ToString()); 262 | break; 263 | } 264 | } 265 | 266 | 267 | if(expectSizeException || expectUnknownException) 268 | { 269 | Assert.Fail("Image Expection was expected!!"); 270 | } 271 | Assert.IsNotNull(result); 272 | 273 | if (bool.Parse(this.TestContext.DataRow["Cache"].ToString())) 274 | { 275 | Assert.IsTrue(!string.IsNullOrWhiteSpace(result.CacheID), "Expected CacheId, Response: {0}", JsonConvert.SerializeObject(result)); 276 | } 277 | else 278 | { 279 | Assert.IsTrue(string.IsNullOrWhiteSpace(result.CacheID), "CacheId NOT EXPECTED, Response: {0}", JsonConvert.SerializeObject(result)); 280 | } 281 | 282 | 283 | 284 | 285 | var textExpected = bool.Parse(this.TestContext.DataRow["TextExpected"].ToString()); 286 | string expectedText = this.TestContext.DataRow["ExpectedText"].ToString(); 287 | var isEnhanced = bool.Parse(this.TestContext.DataRow["Enhanced"].ToString()); 288 | 289 | expectedText = expectedText.Replace(@"\r\n", Environment.NewLine); 290 | 291 | 292 | if (textExpected) 293 | { 294 | Assert.IsTrue( 295 | result.Text == expectedText, 296 | "Unexpected Text: {0}", 297 | JsonConvert.SerializeObject(result)); 298 | 299 | if(isEnhanced) 300 | Assert.IsTrue( 301 | result.Candidates.Count > 0, 302 | "Expected Candidates, Response: {0}", 303 | JsonConvert.SerializeObject(result)); 304 | else 305 | { 306 | Assert.IsTrue( 307 | result.Candidates.Count == 0, 308 | "Did not expect Candidates, Response: {0}", 309 | JsonConvert.SerializeObject(result)); 310 | } 311 | 312 | } 313 | } 314 | catch (Microsoft.CognitiveServices.ContentModerator.ClientException ex) 315 | { 316 | 317 | if(expectSizeException) 318 | { 319 | Assert.AreEqual("Image Size Error",ex.Error.Message); 320 | } 321 | if(expectUnknownException) 322 | { 323 | Assert.AreEqual("Unknown Server Error.",ex.Error.Message); 324 | } 325 | } 326 | } 327 | 328 | 329 | [TestMethod] 330 | [DataSource("IdentifyLanguage")] 331 | [TestCategory("Data Driven")] 332 | public async Task IdentifyLanguage() 333 | { 334 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 335 | if (!isEnabled) 336 | { 337 | return; 338 | } 339 | 340 | var inputText = this.TestContext.DataRow["InputText"].ToString(); 341 | var expectedLanguage = this.TestContext.DataRow["ExpectedLanguage"].ToString().Trim(); 342 | 343 | var result = await this.client.IdentifyLanguageAsync(inputText, Constants.MediaType.Plain); 344 | Assert.IsNotNull(result); 345 | Assert.IsTrue(result.Status != null && result.Status.Code == "3000"); 346 | Assert.IsTrue(!string.IsNullOrWhiteSpace(result.DetectedLanguage)); 347 | Assert.IsTrue(result.DetectedLanguage.Equals(expectedLanguage,StringComparison.OrdinalIgnoreCase)); 348 | } 349 | 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ContentModeratorSDK")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ContentModeratorSDK")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4c761ca8-efb3-4aa8-8999-9d58c50033a2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/ReviewTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using Microsoft.CognitiveServices.ContentModerator; 6 | using Microsoft.CognitiveServices.ContentModerator.Contract.Review; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace ContentModeratorSDK.Test 10 | { 11 | using System.Configuration; 12 | 13 | /// 14 | /// Summary description for ReviewTests 15 | /// 16 | [TestClass] 17 | public class ReviewTests 18 | { 19 | private readonly ReviewClient client = null; 20 | private readonly string testImageContent = @"Content\sample.jpg"; 21 | private readonly string reviewTeamName; 22 | public ReviewTests() 23 | { 24 | this.client = new ReviewClient(ConfigurationManager.AppSettings["subscriptionkey"], ConfigurationManager.AppSettings["Review.ClientId"],ConfigurationManager.AppSettings["Review.ClientSecret"]); 25 | this.reviewTeamName = ConfigurationManager.AppSettings["Review.TeamName"]; 26 | } 27 | 28 | /// 29 | ///Gets or sets the test context which provides 30 | ///information about and functionality for the current test run. 31 | /// 32 | public TestContext TestContext { get; set; } 33 | 34 | [TestMethod] 35 | public void GetReviewDetails() 36 | { 37 | var task = this.client.GetReview(this.reviewTeamName , "Review Id"); 38 | var result = task.Result; 39 | Assert.IsNotNull(result); 40 | } 41 | 42 | [TestMethod] 43 | public void CreateReview() 44 | { 45 | List revrequests = new List(); 46 | List mData = new List(); 47 | KeyValue kv = new KeyValue() 48 | { 49 | Key = "a", 50 | Value = "True" 51 | }; 52 | mData.Add(kv); 53 | kv = new KeyValue() 54 | { 55 | Key = "r", 56 | Value = "False" 57 | }; 58 | mData.Add(kv); 59 | ReviewRequest req1 = new ReviewRequest() 60 | { 61 | CallbackEndpoint = string.Empty, 62 | Content = "https://moderatorsampleimages.blob.core.windows.net/samples/sample.jpg", 63 | ContentId = "sample.jpg", 64 | Type = ContentType.Image, 65 | Metadata = mData 66 | }; 67 | revrequests.Add(req1); 68 | var task = this.client.CreateReview(this.reviewTeamName, revrequests); 69 | var result = task.Result; 70 | Assert.IsNotNull(result); 71 | } 72 | 73 | [TestMethod] 74 | public void GetJobDetails() 75 | { 76 | var task = this.client.GetJobDetails(this.reviewTeamName, ""); 77 | var result = task.Result; 78 | Assert.IsNotNull(result); 79 | } 80 | 81 | [TestMethod] 82 | public void CreateJob() 83 | { 84 | var task = this.client.CreateJob(this.reviewTeamName, "https://hashblobsm2.blob.core.windows.net/testimages/BMPOCR.bmp", ContentType.Image, 85 | "ABC.jpg", "default", ""); 86 | var result = task.Result; 87 | Assert.IsNotNull(result); 88 | } 89 | 90 | [TestMethod] 91 | public void CreateJobStream() 92 | { 93 | CreateJobResult result = null; 94 | using (Stream stream = new FileStream(this.testImageContent, FileMode.Open, FileAccess.Read)) 95 | { 96 | var task = this.client.CreateJob(this.reviewTeamName, stream, ContentType.Image, 97 | "ABC.jpg", "default", ""); 98 | result = task.Result; 99 | } 100 | 101 | Assert.IsNotNull(result); 102 | } 103 | 104 | [TestMethod] 105 | public void GetAllTeamWorkflows() 106 | { 107 | var task = this.client.GetAllWorkflows(this.reviewTeamName); 108 | var result = task.Result; 109 | Assert.IsNotNull(result); 110 | } 111 | 112 | [TestMethod] 113 | public void GetTeamWorkflow() 114 | { 115 | var task = this.client.GetWorkflow(this.reviewTeamName, "default"); 116 | var result = task.Result; 117 | Assert.IsNotNull(result); 118 | } 119 | 120 | [TestMethod] 121 | public void CreateWorkFlowSimple() 122 | { 123 | Condition condition = new Condition() 124 | { 125 | ConnectorName = "imagemoderator", 126 | OutputName = "adultscore", 127 | Operator = ConditionOperator.ge, 128 | Value = "0.4" 129 | }; 130 | 131 | 132 | var task = this.client.CreateWorkFlow(this.reviewTeamName, "MySimpleWorkFlow", "This is a simple workflow", condition); 133 | var result = task.Result; 134 | Assert.IsTrue(result); 135 | } 136 | 137 | [TestMethod] 138 | public void CreateWorkFlowComplex() 139 | { 140 | Condition c1 = new Condition() 141 | { 142 | ConnectorName = "imagemoderator", 143 | OutputName = "isadult", 144 | Operator = ConditionOperator.eq, 145 | Value = "true" 146 | }; 147 | 148 | Condition c2 = new Condition() 149 | { 150 | ConnectorName = "imagemoderator", 151 | OutputName = "isracy", 152 | Operator = ConditionOperator.eq, 153 | Value = "true" 154 | }; 155 | 156 | Condition c3 = new Condition() 157 | { 158 | ConnectorName = "imagemoderator", 159 | OutputName = "adultscore", 160 | Operator = ConditionOperator.ge, 161 | Value = "0.4" 162 | }; 163 | 164 | Condition c4 = new Condition() 165 | { 166 | ConnectorName = "imagemoderator", 167 | OutputName = "racyscore", 168 | Operator = ConditionOperator.ge, 169 | Value = "0.5" 170 | }; 171 | 172 | Combination combine1 = new Combination() 173 | { 174 | Left = c1, 175 | Combine = CombineCondition.AND, 176 | Right = c3, 177 | }; 178 | 179 | Combination combine2 = new Combination() 180 | { 181 | Left = c2, 182 | Combine = CombineCondition.AND, 183 | Right = c4, 184 | }; 185 | 186 | Combination parent = new Combination() 187 | { 188 | Left = combine1, 189 | Combine = CombineCondition.OR, 190 | Right = combine2 191 | }; 192 | 193 | var task = this.client.CreateWorkFlow(this.reviewTeamName, "MyComplexWorkflow", "This is a complex workflow", parent); 194 | var result = task.Result; 195 | Assert.IsTrue(result); 196 | } 197 | 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/TextListScreenScenarios.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ContentModeratorSDK.Test 8 | { 9 | using Microsoft.CognitiveServices.ContentModerator; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using System.Configuration; 12 | using System.Threading; 13 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 14 | 15 | [TestClass] 16 | public class TextListScreenScenarios 17 | { 18 | private static string listId = ""; 19 | 20 | private readonly ListManagementClient textListclient = null; 21 | private readonly ModeratorClient moderatorClient = null; 22 | public TextListScreenScenarios() 23 | { 24 | this.textListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 25 | this.moderatorClient = new ModeratorClient(ConfigurationManager.AppSettings["subscriptionkey"]); 26 | } 27 | 28 | /// 29 | ///Gets or sets the test context which provides 30 | ///information about and functionality for the current test run. 31 | /// 32 | public TestContext TestContext { get; set; } 33 | 34 | [ClassInitialize()] 35 | public static void ClassInitialize(TestContext testContext) 36 | { 37 | //Create a new list 38 | //Get all Lists to verify creation 39 | 40 | var textListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 41 | var listName = Guid.NewGuid().ToString("n"); 42 | 43 | Dictionary listMetaData = new Dictionary(); 44 | listMetaData.Add("MyListMData1", "MyListMData1"); 45 | listMetaData.Add("MyListMData2", "MyListMData2"); 46 | 47 | var createRes = textListclient.TermListCreateAsync(listName, "This is Unit Test", listMetaData) 48 | .ConfigureAwait(false) 49 | .GetAwaiter().GetResult(); 50 | Assert.IsNotNull(createRes); 51 | Assert.IsTrue(!string.IsNullOrWhiteSpace(createRes.Id)); 52 | 53 | listId = createRes.Id; 54 | 55 | var getAllRes = textListclient.TermListGetAllAsync().ConfigureAwait(false) 56 | .GetAwaiter().GetResult(); 57 | Assert.IsNotNull(getAllRes); 58 | Assert.IsTrue(getAllRes.Count > 0); 59 | Assert.IsTrue(getAllRes.Exists(e => e.Id == createRes.Id)); 60 | 61 | Dictionary x = new Dictionary(); 62 | 63 | 64 | 65 | } 66 | 67 | [ClassCleanup()] 68 | public static void ClassCleanup() 69 | { 70 | //Delete ALL Images 71 | //Delete Image List 72 | //Call get all lists to verify deletion 73 | 74 | var textListclient = new ListManagementClient(ConfigurationManager.AppSettings["subscriptionkey"]); 75 | 76 | var updateImageList = textListclient.TermListUpdateAsync(listId, "Updated Name", "Updated", null).ConfigureAwait(false) 77 | .GetAwaiter().GetResult(); 78 | Assert.IsNotNull(updateImageList); 79 | 80 | var deleteImageList = textListclient.TermListDeleteAsync(listId).ConfigureAwait(false) 81 | .GetAwaiter().GetResult(); 82 | Assert.IsNotNull(deleteImageList); 83 | 84 | 85 | var getAllRes = textListclient.TermListGetAllAsync().ConfigureAwait(false) 86 | .GetAwaiter().GetResult(); 87 | Assert.IsNotNull(getAllRes); 88 | Assert.IsTrue(!getAllRes.Exists(e => e.Id == listId)); 89 | } 90 | 91 | [TestMethod] 92 | [TestCategory("Data Driven")] 93 | [DataSource("TermMatch")] 94 | public async Task TermMatchTestsAsync() 95 | { 96 | 97 | //Add Term 98 | //Refresh Index 99 | //List all Terms 100 | //Call Screen - Should Match 101 | //Delete Term 102 | //List all Terms 103 | //Refresh Index 104 | //Call Term - Should not Match 105 | 106 | bool isEnabled = bool.Parse(this.TestContext.DataRow["Enabled"].ToString()); 107 | if (!isEnabled) 108 | { 109 | return; 110 | } 111 | 112 | 113 | Thread.Sleep(1000); 114 | 115 | //inputs 116 | var termToAdd = this.TestContext.DataRow["TermToAdd"].ToString(); 117 | var textToScreen = this.TestContext.DataRow["TextToScreen"].ToString(); 118 | var contentType = (Constants.MediaType) Enum.Parse(typeof(Constants.MediaType),this.TestContext.DataRow["ContentType"].ToString()); 119 | var language = this.TestContext.DataRow["Language"].ToString(); 120 | var autoCorrect = bool.Parse(this.TestContext.DataRow["AutoCorrect"].ToString()); 121 | var identifyUrls = bool.Parse(this.TestContext.DataRow["IdentifyUrls"].ToString()); 122 | var detectPii = bool.Parse(this.TestContext.DataRow["Pii"].ToString()); 123 | 124 | //Expected output 125 | var shouldFindMatch = bool.Parse(this.TestContext.DataRow["MatchTerm"].ToString()); 126 | var urlCount = int.Parse(this.TestContext.DataRow["UrlCount"].ToString()); 127 | var emails = int.Parse(this.TestContext.DataRow["Email"].ToString()); 128 | var phones = int.Parse(this.TestContext.DataRow["Phone"].ToString()); 129 | var ipas = int.Parse(this.TestContext.DataRow["IPA"].ToString()); 130 | var addresses = int.Parse(this.TestContext.DataRow["Address"].ToString()); 131 | 132 | var addTextRes = 133 | await 134 | this.textListclient.TermAddAsync(listId, termToAdd, language); 135 | 136 | 137 | 138 | Assert.IsNotNull(addTextRes); 139 | 140 | var refreshIndexRes = await this.textListclient.TermListRefreshIndexAsync(listId, language); 141 | Assert.IsNotNull(refreshIndexRes); 142 | Thread.Sleep(10000); 143 | 144 | 145 | var listAllTermsRes = await this.textListclient.TermGetAllTermsAsync(listId, language); 146 | Assert.IsNotNull(listAllTermsRes); 147 | Assert.IsTrue(listAllTermsRes.Data.Terms.Exists(e => e.Term == termToAdd)); 148 | 149 | 150 | var matchRes = 151 | await this.moderatorClient.ScreenTextAsync(textToScreen, contentType, language,autoCorrect, identifyUrls, detectPii,listId); 152 | Assert.IsNotNull(matchRes); 153 | 154 | if (shouldFindMatch) 155 | { 156 | Assert.IsNotNull(matchRes.Terms); 157 | Assert.IsTrue(matchRes.Terms.ToList().Exists(m => (m.Term == termToAdd) && (m.ListId == listId))); 158 | } 159 | 160 | if(urlCount > 0) 161 | { 162 | Assert.IsTrue(matchRes.Urls.Length == urlCount ); 163 | } 164 | 165 | if(emails > 0) 166 | { 167 | Assert.IsTrue(matchRes.PII.Email.Count == emails); 168 | } 169 | 170 | if(phones > 0) 171 | { 172 | Assert.IsTrue(matchRes.PII.Phone.Count == phones); 173 | } 174 | 175 | if (ipas > 0) 176 | { 177 | Assert.IsTrue(matchRes.PII.IPA.Count == ipas); 178 | } 179 | 180 | if (addresses > 0) 181 | { 182 | Assert.IsTrue(matchRes.PII.Address.Count == addresses); 183 | } 184 | var deleteTermRes = await this.textListclient.TermDeleteAsync(listId, termToAdd, language); 185 | Assert.IsNotNull(deleteTermRes); 186 | 187 | var listAllAfterDeleteTermsRes = await this.textListclient.TermGetAllTermsAsync(listId, language); 188 | Assert.IsNotNull(listAllAfterDeleteTermsRes); 189 | Assert.IsTrue( 190 | !listAllAfterDeleteTermsRes.Data.Terms.Exists(e => e.Term == termToAdd)); 191 | 192 | var refreshIndexAfterDeleteRes = await this.textListclient.TermListRefreshIndexAsync(listId, language); 193 | Assert.IsNotNull(refreshIndexAfterDeleteRes); 194 | Thread.Sleep(10000); 195 | 196 | var matchAfterDeleteRes = 197 | await this.moderatorClient.ScreenTextAsync(textToScreen, contentType, language,autoCorrect, identifyUrls, detectPii,listId); 198 | Assert.IsNotNull(matchAfterDeleteRes); 199 | if (matchAfterDeleteRes.Terms != null) 200 | { 201 | Assert.IsTrue( 202 | !matchAfterDeleteRes.Terms.ToList().Exists(m => (m.Term == termToAdd) && (m.ListId == listId))); 203 | } 204 | 205 | 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftContentModerator/Microsoft.CognitiveServices.ContentModerator-Windows/38236497d16cb6020b55b91419610316adb9e49a/ContentModeratorSDK.Tests/data.xlsx -------------------------------------------------------------------------------- /ContentModeratorSDK.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ContentModeratorSDK.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContentModeratorSDK", "ContentModeratorSDK\ContentModeratorSDK.csproj", "{961284A5-1E23-416B-ABA0-FF28C2327CAB}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContentModeratorSDK.Test", "ContentModeratorSDK.Tests\ContentModeratorSDK.Test.csproj", "{4C761CA8-EFB3-4AA8-8999-9D58C50033A2}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Release|Any CPU = Release|Any CPU 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Debug|x64.ActiveCfg = Debug|Any CPU 21 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Debug|x64.Build.0 = Debug|Any CPU 22 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Release|x64.ActiveCfg = Release|Any CPU 25 | {961284A5-1E23-416B-ABA0-FF28C2327CAB}.Release|x64.Build.0 = Release|Any CPU 26 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Debug|x64.ActiveCfg = Debug|x64 29 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Debug|x64.Build.0 = Debug|x64 30 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Release|x64.ActiveCfg = Release|x64 33 | {4C761CA8-EFB3-4AA8-8999-9D58C50033A2}.Release|x64.Build.0 = Release|x64 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(TeamFoundationVersionControl) = preSolution 39 | SccNumberOfProjects = 3 40 | SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} 41 | SccLocalPath0 = . 42 | SccProjectUniqueName1 = ContentModeratorSDK_V2\\ContentModeratorSDK.csproj 43 | SccProjectName1 = ContentModeratorSDK_V2 44 | SccLocalPath1 = ContentModeratorSDK_V2 45 | SccProjectUniqueName2 = ContentModeratorSDK\\ContentModeratorSDK.Test.csproj 46 | SccProjectName2 = ContentModeratorSDK 47 | SccLocalPath2 = ContentModeratorSDK 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ClientBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator 8 | { 9 | using System.IO; 10 | using System.Net; 11 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Serialization; 14 | 15 | public abstract class ClientBase 16 | { 17 | 18 | /// 19 | /// The subscription key 20 | /// 21 | protected string SubscriptionKey; 22 | 23 | /// 24 | /// The root URI for Vision API 25 | /// 26 | protected string ApiRoot; 27 | 28 | /// 29 | /// Default timeout for calls 30 | /// 31 | protected const int DEFAULT_TIMEOUT = 2 * 60 * 1000; // 2 minutes timeout 32 | 33 | /// 34 | /// Default timeout for calls, overridable by subclasses 35 | /// 36 | protected virtual int DefaultTimeout => DEFAULT_TIMEOUT; 37 | 38 | /// 39 | /// The default resolver 40 | /// 41 | private readonly CamelCasePropertyNamesContractResolver defaultResolver = new CamelCasePropertyNamesContractResolver(); 42 | 43 | 44 | protected async Task InvokeAsync(dynamic imageRequest, string operationUrl, Constants.HttpMethod method, List metaData = null) 45 | { 46 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, operationUrl, "?")); 47 | 48 | if (metaData != null) 49 | { 50 | foreach (var k in metaData) 51 | { 52 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 53 | requestUrl.Append("&"); 54 | } 55 | } 56 | var request = WebRequest.Create(requestUrl.ToString()); 57 | 58 | return 59 | await 60 | this.SendAsync(method.ToString(), imageRequest, request); 61 | } 62 | 63 | protected async Task InvokeAsync(string operationUrl, Constants.HttpMethod method, List metaData = null) 64 | { 65 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, operationUrl, "?")); 66 | 67 | if (metaData != null) 68 | { 69 | foreach (var k in metaData) 70 | { 71 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 72 | requestUrl.Append("&"); 73 | } 74 | } 75 | 76 | var request = WebRequest.Create(requestUrl.ToString()); 77 | 78 | 79 | if (method != Constants.HttpMethod.GET) 80 | { 81 | request.ContentLength = 0; 82 | } 83 | 84 | 85 | 86 | return 87 | await 88 | this.GetAsync(method.ToString(), request); 89 | } 90 | 91 | 92 | 93 | 94 | /// 95 | /// Gets the asynchronous. 96 | /// 97 | /// The type of the response. 98 | /// The method. 99 | /// The request. 100 | /// The set headers callback. 101 | /// 102 | /// The response object. 103 | /// 104 | protected async Task GetAsync(string method, WebRequest request, Action setHeadersCallback = null) 105 | { 106 | if (request == null) 107 | { 108 | throw new ArgumentNullException(nameof(request)); 109 | } 110 | 111 | try 112 | { 113 | request.Method = method; 114 | request.Headers.Add("Ocp-Apim-Subscription-Key", this.SubscriptionKey); 115 | 116 | if (null == setHeadersCallback) 117 | { 118 | this.SetCommonHeaders(request); 119 | } 120 | else 121 | { 122 | setHeadersCallback(request); 123 | } 124 | 125 | var getResponse = Task.Factory.FromAsync( 126 | request.BeginGetResponse, 127 | request.EndGetResponse, 128 | null); 129 | 130 | await Task.WhenAny(getResponse, Task.Delay(this.DefaultTimeout)); 131 | 132 | //Abort request if timeout has expired 133 | if (!getResponse.IsCompleted) 134 | { 135 | request.Abort(); 136 | } 137 | 138 | return this.ProcessAsyncResponse(getResponse.Result as HttpWebResponse); 139 | } 140 | catch (AggregateException ae) 141 | { 142 | ae.Handle(e => 143 | { 144 | this.HandleException(e); 145 | return true; 146 | }); 147 | return default(TResponse); 148 | } 149 | catch (Exception e) 150 | { 151 | this.HandleException(e); 152 | return default(TResponse); 153 | } 154 | } 155 | 156 | /// 157 | /// Sends the asynchronous. 158 | /// 159 | /// The type of the request. 160 | /// The type of the response. 161 | /// The method. 162 | /// The request body. 163 | /// The request. 164 | /// The set headers callback. 165 | /// The response object. 166 | /// request 167 | protected async Task SendAsync(string method, TRequest requestBody, WebRequest request, Action setHeadersCallback = null) 168 | { 169 | try 170 | { 171 | if (request == null) 172 | { 173 | throw new ArgumentNullException(nameof(request)); 174 | } 175 | 176 | request.Method = method; 177 | request.Headers.Add("Ocp-Apim-Subscription-Key", this.SubscriptionKey); 178 | 179 | if (null == setHeadersCallback) 180 | { 181 | if (string.IsNullOrWhiteSpace(request.ContentType)) 182 | this.SetCommonHeaders(request); 183 | } 184 | else 185 | { 186 | setHeadersCallback(request); 187 | } 188 | 189 | if (requestBody is Stream) 190 | { 191 | request.ContentType = $"image/jpeg"; 192 | } 193 | 194 | var asyncState = new WebRequestAsyncState() 195 | { 196 | RequestBytes = this.SerializeRequestBody(requestBody, request.ContentType), 197 | WebRequest = (HttpWebRequest)request, 198 | }; 199 | 200 | var continueRequestAsyncState = await Task.Factory.FromAsync( 201 | asyncState.WebRequest.BeginGetRequestStream, 202 | asyncState.WebRequest.EndGetRequestStream, 203 | asyncState, 204 | TaskCreationOptions.None).ContinueWith( 205 | task => 206 | { 207 | var requestAsyncState = (WebRequestAsyncState)task.AsyncState; 208 | if (requestBody != null) 209 | { 210 | using (var requestStream = task.Result) 211 | { 212 | if (requestBody is Stream) 213 | { 214 | (requestBody as Stream).CopyTo(requestStream); 215 | } 216 | else 217 | { 218 | requestStream.Write(requestAsyncState.RequestBytes, 0, requestAsyncState.RequestBytes.Length); 219 | } 220 | } 221 | } 222 | 223 | return requestAsyncState; 224 | }); 225 | 226 | var continueWebRequest = continueRequestAsyncState.WebRequest; 227 | var getResponse = Task.Factory.FromAsync( 228 | continueWebRequest.BeginGetResponse, 229 | continueWebRequest.EndGetResponse, 230 | continueRequestAsyncState); 231 | 232 | await Task.WhenAny(getResponse, Task.Delay(this.DefaultTimeout)); 233 | 234 | //Abort request if timeout has expired 235 | if (!getResponse.IsCompleted) 236 | { 237 | request.Abort(); 238 | } 239 | 240 | return this.ProcessAsyncResponse(getResponse.Result as HttpWebResponse); 241 | } 242 | catch (AggregateException ae) 243 | { 244 | ae.Handle(e => 245 | { 246 | this.HandleException(e); 247 | return true; 248 | }); 249 | return default(TResponse); 250 | } 251 | catch (Exception e) 252 | { 253 | this.HandleException(e); 254 | return default(TResponse); 255 | } 256 | } 257 | 258 | /// 259 | /// Processes the asynchronous response. 260 | /// 261 | /// Type of response. 262 | /// The web response. 263 | /// The response. 264 | protected T ProcessAsyncResponse(HttpWebResponse webResponse) 265 | { 266 | using (webResponse) 267 | { 268 | if (webResponse.StatusCode == HttpStatusCode.OK || 269 | webResponse.StatusCode == HttpStatusCode.Accepted || 270 | webResponse.StatusCode == HttpStatusCode.Created) 271 | { 272 | if (webResponse.ContentLength != 0) 273 | { 274 | using (var stream = webResponse.GetResponseStream()) 275 | { 276 | if (stream != null) 277 | { 278 | if (webResponse.ContentType == "image/jpeg" || 279 | webResponse.ContentType == "image/png") 280 | { 281 | using (MemoryStream ms = new MemoryStream()) 282 | { 283 | stream.CopyTo(ms); 284 | return (T)(object)ms.ToArray(); 285 | } 286 | } 287 | else 288 | { 289 | string message; 290 | using (var reader = new StreamReader(stream)) 291 | { 292 | message = reader.ReadToEnd(); 293 | } 294 | 295 | JsonSerializerSettings settings = new JsonSerializerSettings(); 296 | settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 297 | settings.NullValueHandling = NullValueHandling.Ignore; 298 | settings.ContractResolver = this.defaultResolver; 299 | 300 | return JsonConvert.DeserializeObject(message, settings); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | 308 | return default(T); 309 | } 310 | 311 | /// 312 | /// Set request content type. 313 | /// 314 | /// Web request object. 315 | private void SetCommonHeaders(WebRequest request) 316 | { 317 | request.ContentType = "application/json"; 318 | } 319 | 320 | 321 | /// 322 | /// Serialize the request body to byte array 323 | /// 324 | /// Type of request object 325 | /// Strong typed request object 326 | /// Content Type of the Request 327 | /// Byte array 328 | private byte[] SerializeRequestBody(T requestBody, string contentType) 329 | { 330 | byte[] data = null; 331 | if (requestBody != null && !(requestBody is Stream)) 332 | { 333 | if (contentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { 334 | JsonSerializerSettings settings = new JsonSerializerSettings(); 335 | settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 336 | settings.ContractResolver = this.defaultResolver; 337 | data = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(requestBody, settings)); } else { 338 | data = System.Text.Encoding.UTF8.GetBytes(requestBody as string); } 339 | } 340 | 341 | return data; 342 | } 343 | 344 | /// 345 | /// Process the exception happened on rest call. 346 | /// 347 | /// Exception object. 348 | private void HandleException(Exception exception) 349 | { 350 | WebException webException = exception as WebException; 351 | if (webException != null && webException.Response != null) 352 | { 353 | if (webException.Response.ContentType.ToLower().Contains("application/json")) 354 | { 355 | Stream stream = null; 356 | 357 | try 358 | { 359 | stream = webException.Response.GetResponseStream(); 360 | if (stream != null) 361 | { 362 | string errorObjectString; 363 | using (StreamReader reader = new StreamReader(stream)) 364 | { 365 | stream = null; 366 | errorObjectString = reader.ReadToEnd(); 367 | } 368 | 369 | ClientError errorCollection = JsonConvert.DeserializeObject(errorObjectString); 370 | if (errorCollection != null) 371 | { 372 | throw new ClientException 373 | { 374 | Error = errorCollection, 375 | }; 376 | } 377 | } 378 | } 379 | finally 380 | { 381 | stream?.Dispose(); 382 | } 383 | } 384 | } 385 | 386 | throw exception; 387 | } 388 | 389 | 390 | /// 391 | /// This class is used to pass on "state" between each Begin/End call 392 | /// It also carries the user supplied "state" object all the way till 393 | /// the end where is then hands off the state object to the 394 | /// WebRequestCallbackState object. 395 | /// 396 | internal class WebRequestAsyncState 397 | { 398 | /// 399 | /// Gets or sets request bytes of the request parameter for http post. 400 | /// 401 | public byte[] RequestBytes { get; set; } 402 | 403 | /// 404 | /// Gets or sets the HttpWebRequest object. 405 | /// 406 | public HttpWebRequest WebRequest { get; set; } 407 | 408 | /// 409 | /// Gets or sets the request state object. 410 | /// 411 | public object State { get; set; } 412 | } 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ClientError.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. 4 | // 5 | // Microsoft Cognitive Services (formerly Project Oxford): https://www.microsoft.com/cognitive-services 6 | // 7 | // Microsoft Cognitive Services (formerly Project Oxford) GitHub: 8 | // https://github.com/Microsoft/Cognitive-Vision-Windows 9 | // 10 | // Copyright (c) Microsoft Corporation 11 | // All rights reserved. 12 | // 13 | // MIT License: 14 | // Permission is hereby granted, free of charge, to any person obtaining 15 | // a copy of this software and associated documentation files (the 16 | // "Software"), to deal in the Software without restriction, including 17 | // without limitation the rights to use, copy, modify, merge, publish, 18 | // distribute, sublicense, and/or sell copies of the Software, and to 19 | // permit persons to whom the Software is furnished to do so, subject to 20 | // the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be 23 | // included in all copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, 26 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | // 33 | 34 | using System; 35 | 36 | namespace Microsoft.CognitiveServices.ContentModerator 37 | { 38 | /// 39 | /// Container of ClientError and Error Entity. 40 | /// 41 | public class ClientError 42 | { 43 | /// 44 | /// Gets or sets error code in error entity. 45 | /// 46 | public string Code 47 | { 48 | get; 49 | set; 50 | } 51 | 52 | /// 53 | /// Gets or sets the message. 54 | /// 55 | /// 56 | /// The message. 57 | /// 58 | public string Message 59 | { 60 | get; 61 | set; 62 | } 63 | 64 | /// 65 | /// Gets or sets the request identifier. 66 | /// 67 | /// 68 | /// The request identifier. 69 | /// 70 | public Guid RequestId { get; set; } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ClientException.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. 4 | // 5 | // Microsoft Cognitive Services (formerly Project Oxford): https://www.microsoft.com/cognitive-services 6 | // 7 | // Microsoft Cognitive Services (formerly Project Oxford) GitHub: 8 | // https://github.com/Microsoft/Cognitive-Vision-Windows 9 | // 10 | // Copyright (c) Microsoft Corporation 11 | // All rights reserved. 12 | // 13 | // MIT License: 14 | // Permission is hereby granted, free of charge, to any person obtaining 15 | // a copy of this software and associated documentation files (the 16 | // "Software"), to deal in the Software without restriction, including 17 | // without limitation the rights to use, copy, modify, merge, publish, 18 | // distribute, sublicense, and/or sell copies of the Software, and to 19 | // permit persons to whom the Software is furnished to do so, subject to 20 | // the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be 23 | // included in all copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, 26 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | // 33 | 34 | using System; 35 | using System.Net; 36 | 37 | namespace Microsoft.CognitiveServices.ContentModerator 38 | { 39 | /// 40 | /// The Exception will be shown to client. 41 | /// 42 | public class ClientException : Exception 43 | { 44 | /// 45 | /// Initializes a new instance of the class. 46 | /// 47 | public ClientException() 48 | : base() 49 | { 50 | } 51 | 52 | /// 53 | /// Initializes a new instance of the class. 54 | /// 55 | /// The corresponding error message. 56 | public ClientException(string message) 57 | : base(message) 58 | { 59 | this.Error = new ClientError() 60 | { 61 | Code = HttpStatusCode.InternalServerError.ToString(), 62 | Message = message 63 | }; 64 | } 65 | 66 | /// 67 | /// Initializes a new instance of the class. 68 | /// 69 | /// The corresponding error message. 70 | /// The Http Status code. 71 | public ClientException(string message, HttpStatusCode httpStatus) 72 | : base(message) 73 | { 74 | this.HttpStatus = httpStatus; 75 | 76 | this.Error = new ClientError() 77 | { 78 | Code = this.HttpStatus.ToString(), 79 | Message = message 80 | }; 81 | } 82 | 83 | /// 84 | /// Initializes a new instance of the class. 85 | /// 86 | /// The corresponding error message. 87 | /// The inner exception. 88 | public ClientException(string message, Exception innerException) 89 | : base(message, innerException) 90 | { 91 | this.Error = new ClientError() 92 | { 93 | Code = HttpStatusCode.InternalServerError.ToString(), 94 | Message = message 95 | }; 96 | } 97 | 98 | /// 99 | /// Initializes a new instance of the class. 100 | /// 101 | /// The corresponding error message. 102 | /// The error code. 103 | /// The http status. 104 | /// The inner exception. 105 | public ClientException(string message, string errorCode, HttpStatusCode httpStatus, Exception innerException) 106 | : base(message, innerException) 107 | { 108 | this.HttpStatus = httpStatus; 109 | 110 | this.Error = new ClientError() 111 | { 112 | Code = errorCode, 113 | Message = message 114 | }; 115 | } 116 | 117 | /// 118 | /// Initializes a new instance of the class. 119 | /// 120 | /// The error entity. 121 | /// The http status. 122 | public ClientException(ClientError error, HttpStatusCode httpStatus) 123 | { 124 | this.Error = error; 125 | this.HttpStatus = httpStatus; 126 | } 127 | 128 | /// 129 | /// Gets http status of http response. 130 | /// 131 | public HttpStatusCode HttpStatus 132 | { 133 | get; 134 | private set; 135 | } 136 | 137 | /// 138 | /// Gets or sets the httpError message. 139 | /// 140 | public ClientError Error { get; set; } 141 | 142 | /// 143 | /// Create Client Exception of Bad Request. 144 | /// 145 | /// The corresponding error message. 146 | /// Client Exception Instance. 147 | public static ClientException BadRequest(string message) 148 | { 149 | return new ClientException( 150 | new ClientError() 151 | { 152 | Code = ((int)HttpStatusCode.BadRequest).ToString(), 153 | Message = message 154 | }, 155 | HttpStatusCode.BadRequest); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.CognitiveServices.ContentModerator 9 | { 10 | public class Constants 11 | { 12 | public enum Operations 13 | { 14 | Evaluate, 15 | FindFaces, 16 | OCR, 17 | Match, 18 | Screen, 19 | DetectLanguage, 20 | 21 | } 22 | 23 | public enum HttpMethod 24 | { 25 | POST, 26 | GET, 27 | DELETE, 28 | PUT 29 | } 30 | 31 | public enum MediaType 32 | { 33 | [Description("text/html")] 34 | Html, 35 | [Description("text/markdown")] 36 | MarkDown, 37 | [Description("text/plain")] 38 | Plain, 39 | [Description("text/xml")] 40 | Xml, 41 | [Description("application/json")] 42 | ApplicationJson, 43 | [Description("image/jpeg")] 44 | ImageJpeg, 45 | [Description("image/png")] 46 | ImagePng, 47 | } 48 | 49 | #region Image Urls 50 | 51 | public const string IMAGE_ADD = "/imagelists/{0}/images"; 52 | public const string IMAGE_DELETE = "/imagelists/{0}/images/{1}"; 53 | public const string IMAGE_DELETEALL = "/imagelists/{0}/images"; 54 | public const string IMAGE_GETALLIDS = "/imagelists/{0}/Images"; 55 | #endregion 56 | 57 | #region Image Lists 58 | public const string IMAGELIST_CREATE = "/imagelists"; 59 | public const string IMAGELIST_UPDATE = "/imagelists/{0}"; 60 | public const string IMAGELIST_REFRESHINDEX = "/imagelists/{0}/RefreshIndex"; 61 | public const string IMAGELIST_GETALL = "/imagelists"; 62 | public const string IMAGELIST_GETDETAIL = "/imagelists/{0}"; 63 | public const string IMAGELIST_DELETE = "/imagelists/{0}"; 64 | #endregion 65 | 66 | 67 | #region Term Urls 68 | 69 | public const string TERM_ADD = "/termlists/{0}/terms/{1}"; 70 | public const string TERM_DELETE = "/termlists/{0}/terms/{1}"; 71 | public const string TERM_DELETEALL = "/termlists/{0}/terms"; 72 | public const string TERM_GETALLIDS = "/termlists/{0}/terms"; 73 | #endregion 74 | 75 | #region Term Lists 76 | public const string TERMLIST_CREATE = "/termlists"; 77 | public const string TERMLIST_UPDATE = "/termlists/{0}"; 78 | public const string TERMLIST_REFRESHINDEX = "/termlists/{0}/RefreshIndex"; 79 | public const string TERMLIST_GETALL = "/termlists"; 80 | public const string TERMLIST_GETDETAIL = "/termlists/{0}"; 81 | public const string TERMLIST_DELETE = "/termlists/{0}"; 82 | #endregion 83 | 84 | #region Review Urls 85 | public const string GET_REVIEW_DETAILS = "/teams/{0}/reviews/{1}"; 86 | public const string CREATE_REVIEW = "/teams/{0}/reviews"; 87 | public const string GET_JOB_DETAILS = "/teams/{0}/jobs/{1}"; 88 | public const string CREATE_JOB = "/teams/{0}/jobs"; 89 | public const string GET_ALL_TEAM_WORKFLOWS = "/teams/{0}/workflows"; 90 | public const string GET_TEAM_WORKFLOW = "/teams/{0}/workflows/{1}"; 91 | public const string CREATE_WORKFLOW = "/teams/{0}/workflows/{1}"; 92 | 93 | #endregion 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ContentModeratorSDK.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {961284A5-1E23-416B-ABA0-FF28C2327CAB} 8 | Library 9 | Properties 10 | Microsoft.CognitiveServices.ContentModerator 11 | Microsoft.CognitiveServices.ContentModerator 12 | v4.5.2 13 | 512 14 | SAK 15 | SAK 16 | SAK 17 | SAK 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | AnyCPU 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | ..\packages\Microsoft.Rest.ClientRuntime.0.9.6\lib\net45\Microsoft.Rest.ClientRuntime.dll 40 | True 41 | 42 | 43 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 44 | True 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Always 100 | 101 | 102 | Always 103 | 104 | 105 | 106 | 107 | 108 | Always 109 | 110 | 111 | 112 | 113 | "nugetpackager\PostBuildCommand.bat" "$(TargetPath)" "$(ProjectName)" "$(ProjectDir)" "$(TargetDir)" 114 | 115 | 122 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/AdvancedInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | /// 10 | /// Name value pair with detailed information on the response 11 | /// 12 | public class AdvancedInfo 13 | { 14 | public string Key; 15 | public string Value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/DataRepresentation.cs: -------------------------------------------------------------------------------- 1 | // ----------------------------------------------------------------------- 2 | // 3 | // Copyright (C) Microsoft Corporation. All rights reserved. 4 | // 5 | // ----------------------------------------------------------------------- 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | /// 10 | /// Data representation for the API 11 | /// 12 | public enum DataRepresentationType 13 | { 14 | Url, 15 | Cacheid 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/DetectFacesResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class DetectFacesResult : ImageResult 10 | { 11 | /// 12 | /// Advanced Information from the DetectFace 13 | /// 14 | public AdvancedInfo[] AdvancedInfo; 15 | 16 | /// 17 | /// Boolean indicating whether face are detected 18 | /// 19 | public bool Result; 20 | 21 | /// 22 | /// Faces detected 23 | /// 24 | public double Count; 25 | 26 | /// 27 | /// Face dimensions 28 | /// 29 | public Faces[] Faces; 30 | } 31 | 32 | /// 33 | /// Face dimensions 34 | /// 35 | public class Faces 36 | { 37 | /// 38 | /// Face bottom 39 | /// 40 | public double Bottom; 41 | 42 | /// 43 | /// Face Left 44 | /// 45 | public double Left; 46 | 47 | /// 48 | /// Face Right 49 | /// 50 | public double Right; 51 | 52 | /// 53 | /// Face Top. 54 | /// 55 | public double Top; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/EvaluateImageResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | /// 10 | /// Response from evaluating an image. The response contains the following information 11 | /// 1. Score: Returned within the AdvancedInfo, the score contains the actual score from 12 | /// the adult content classifier. 13 | /// 2. Result: Result contains the result of evaluation. 14 | /// 15 | public class EvaluateImageResult : ImageResult 16 | { 17 | /// 18 | /// Array of name value pairs wit specific information about evaluate 19 | /// 20 | public AdvancedInfo[] AdvancedInfo; 21 | 22 | /// 23 | /// Image adult classification score 24 | /// 25 | public double AdultClassificationScore; 26 | 27 | /// 28 | /// Image is in adult category 29 | /// 30 | public bool IsImageAdultClassified; 31 | 32 | /// 33 | /// Image is in racism category 34 | /// 35 | public bool IsImageRacyClassified; 36 | 37 | /// 38 | /// Image racy classification score 39 | /// 40 | public double RacyClassificationScore; 41 | 42 | /// 43 | /// Image Evaluation Result 44 | /// 45 | public bool Result { get; set; } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/ImageAddResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class ImageAddResult : Result 10 | { 11 | /// 12 | /// Detailed information from image add action 13 | /// 14 | public AdvancedInfo[] AdditionalInfo; 15 | 16 | /// 17 | /// Id of added image 18 | /// 19 | public string ContentId; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/ImageListResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class ImageListResult :Result 10 | { 11 | public string ContentSource { get; set; } 12 | public List ContentIds { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/ImageRefreshIndexResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class ImageRefreshIndexResult : Result 10 | { 11 | /// 12 | /// Advanced Information from the request 13 | /// 14 | public AdvancedInfo[] AdvancedInfo; 15 | 16 | /// 17 | /// Boolean indicating if the update was succssful 18 | /// 19 | public bool IsUpdateSuccess; 20 | 21 | /// 22 | /// Content Source refreshed 23 | /// 24 | public string ContentSourceId; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/ImageResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class ImageResult : Result 10 | { 11 | public string CacheID { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/KeyValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | /// 10 | /// Key value pairs for passing additional meta data info. 11 | /// 12 | public class KeyValue 13 | { 14 | public string Key { get; set; } 15 | 16 | public string Value { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/MatchResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class MatchResult : ImageResult 10 | { 11 | /// 12 | /// Boolean indicating whether an image is a match 13 | /// 14 | public bool IsMatch; 15 | 16 | /// 17 | /// Match details 18 | /// 19 | public List Matches; 20 | } 21 | 22 | public class Match 23 | { 24 | /// 25 | /// Match score. 1 means exact match. 26 | /// 27 | public double Score; 28 | 29 | /// 30 | /// Match ID. 31 | /// 32 | public int MatchId; 33 | 34 | /// 35 | /// Content Source id for the image 36 | /// 37 | public string Source; 38 | 39 | /// 40 | /// All Tag(s) provided while adding the image 41 | /// 42 | public int[] Tags; 43 | 44 | /// 45 | /// Label given when image added 46 | /// 47 | public string Label; 48 | 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/OCRImageResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 8 | { 9 | public class OcrImageResult : ImageResult 10 | { 11 | public OcrImageResult() 12 | { 13 | this.Candidates = new List(); 14 | } 15 | /// 16 | /// Array of name value pairs wit specific information about evaluate 17 | /// 18 | public AdvancedInfo[] AdvancedInfo; 19 | 20 | /// 21 | /// OCR Result Language 22 | /// 23 | public string Language { get; set; } 24 | 25 | /// 26 | /// OCR Text Result 27 | /// 28 | public string Text { get; set; } 29 | 30 | /// 31 | /// OCR Result Candidates 32 | /// 33 | public List Candidates { get; set; } 34 | 35 | } 36 | 37 | public class Candidate 38 | { 39 | /// 40 | /// Text of candidate 41 | /// 42 | public string Text { get; set; } 43 | 44 | /// 45 | /// Confidence score of candidate 46 | /// 47 | public int Confidence { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Image/Result.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Image 2 | { 3 | /// 4 | /// Base class from a Image service result 5 | /// 6 | public class Result 7 | { 8 | /// 9 | /// Status of the result 10 | /// 11 | public Status Status { get; set; } 12 | 13 | public string TrackingId { get; set; } 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/ListItemResult.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.CognitiveServices.ContentModerator.Contract 2 | { 3 | using System.Collections.Generic; 4 | 5 | public class ListItemResult 6 | { 7 | public string Id { get; set; } 8 | public string Name { get; set; } 9 | public string Description { get; set; } 10 | public Dictionary Metadata { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/CreateJobResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 8 | { 9 | public class CreateJobResult 10 | { 11 | public string JobId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/JobDetailsResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | using Newtonsoft.Json.Converters; 8 | 9 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 10 | { 11 | public class JobDetailsResult 12 | { 13 | public JobDetailsResult() 14 | { 15 | this.ResultMetaData = new List(); 16 | } 17 | public string Id { get; set; } 18 | public string TeamName { get; set; } 19 | public JobStatus Status { get; set; } 20 | public string WorkflowId { get; set; } 21 | public string CallBackEndpoint { get; set; } 22 | public string ReviewId { get; set; } 23 | public List ResultMetaData { get; set; } 24 | } 25 | 26 | [JsonConverter(typeof(StringEnumConverter))] 27 | public enum JobStatus 28 | { 29 | Pending = 1, 30 | Complete = 2, 31 | Failed = 3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/KeyValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | using Newtonsoft.Json.Converters; 8 | 9 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 10 | { 11 | public class KeyValue 12 | { 13 | public string Key { get; set; } 14 | 15 | public string Value { get; set; } 16 | } 17 | 18 | [JsonConverter(typeof(StringEnumConverter))] 19 | public enum ContentType 20 | { 21 | Image = 1, 22 | Text = 2, 23 | Video = 3 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/ReviewRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 8 | { 9 | public class ReviewRequest 10 | { 11 | public string Content { get; set; } 12 | public string ContentId { get; set; } 13 | public string CallbackEndpoint { get; set; } 14 | 15 | public IList Metadata { get; set; } 16 | public ContentType Type { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/ReviewResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 8 | { 9 | public class ReviewResponse 10 | { 11 | public string ReviewId { get; set; } 12 | 13 | public ICollection Metadata { get; set; } 14 | 15 | public string Type { get; set; } 16 | 17 | public string Content { get; set; } 18 | 19 | public string ContentId { get; set; } 20 | 21 | public string CallbackEndpoint { get; set; } 22 | 23 | public string Status { get; set; } 24 | 25 | public ICollection ReviewerResultTags { get; set; } 26 | 27 | public string CreatedBy { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/TokenResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 8 | { 9 | public class TokenResult 10 | { 11 | public string token_type { get; set; } 12 | public string expires_in { get; set; } 13 | public string ext_expires_in { get; set; } 14 | public string expires_on { get; set; } 15 | public string not_before { get; set; } 16 | public string resource { get; set; } 17 | public string access_token { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Review/WorkFlowItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | using Newtonsoft.Json.Converters; 8 | 9 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Review 10 | { 11 | public class WorkFlowItem 12 | { 13 | public string Name { get; set; } 14 | public string Description { get; set; } 15 | 16 | public Expression Expression { get; set; } 17 | } 18 | 19 | public abstract class Expression 20 | { 21 | public ExpressionType Type { get; set; } 22 | } 23 | 24 | public class Condition : Expression 25 | { 26 | public Condition() 27 | { 28 | this.Type = ExpressionType.Condition; 29 | } 30 | public string ConnectorName { get; set; } 31 | public string OutputName { get; set; } 32 | 33 | public ConditionOperator Operator { get; set; } 34 | 35 | public string Value { get; set; } 36 | } 37 | 38 | public class Combination : Expression 39 | { 40 | public Combination() 41 | { 42 | this.Type = ExpressionType.Combine; 43 | } 44 | public Expression Left { get; set; } 45 | 46 | public Expression Right { get; set; } 47 | 48 | public CombineCondition Combine { get; set; } 49 | } 50 | 51 | [JsonConverter(typeof(StringEnumConverter))] 52 | public enum CombineCondition 53 | { 54 | AND, 55 | OR 56 | } 57 | 58 | [JsonConverter(typeof(StringEnumConverter))] 59 | public enum ConditionOperator 60 | { 61 | gt, //GreaterThan 62 | lt, //LessThan 63 | ge, //GreaterThanOrEqual 64 | le, //LessThanOrEqual 65 | eq //equal 66 | } 67 | 68 | [JsonConverter(typeof(StringEnumConverter))] 69 | public enum ExpressionType 70 | { 71 | Condition, 72 | Combine 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Status.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract 8 | { 9 | /// 10 | /// Status from a response 11 | /// 12 | public class Status 13 | { 14 | /// 15 | /// Status code 16 | /// 17 | public string Code; 18 | 19 | /// 20 | /// Text describing the response 21 | /// 22 | public string Description; 23 | 24 | /// 25 | /// Observed error 26 | /// 27 | public string Exception; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/IdentifyLanguageResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | /// 10 | /// Result from screening a text, containing details regarding the Match 11 | /// 12 | public class IdentifyLanguageResult : Result 13 | { 14 | public string DetectedLanguage; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/MatchDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | // 10 | // Specific information about a match 11 | // 12 | public class MatchDetails 13 | { 14 | /// 15 | /// Advanced Information from the match 16 | /// 17 | public AdvancedInfo[] AdvancedInfo; 18 | 19 | /// 20 | /// The match flags containing details on the match operation 21 | /// 22 | public MatchFlag[] MatchFlags; 23 | } 24 | 25 | /// 26 | /// Name value pair with detailed information on the response 27 | /// 28 | public class AdvancedInfo 29 | { 30 | public string Key; 31 | public string Value; 32 | } 33 | 34 | /// 35 | /// Information about a match including the source ContentId and the actual score 36 | /// 37 | public class MatchFlag 38 | { 39 | /// 40 | /// Additional details about match 41 | /// 42 | public AdvancedInfo[] AdvancedInfo; 43 | 44 | /// 45 | /// Match score. 1 means exact match. 46 | /// 47 | public double Score; 48 | 49 | /// 50 | /// Match source ContentId 51 | /// 52 | public string Source; 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/MatchTerm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | public class MatchTerm 10 | { 11 | public string Term; 12 | public int Index; 13 | public string ListId; 14 | public string OriginalIndex; 15 | } 16 | 17 | public class MatchUrl 18 | { 19 | public MatchUrlCategories categories; 20 | 21 | public string URL; 22 | } 23 | public class MatchUrlCategories 24 | { 25 | public double Adult; 26 | public double Malware; 27 | public double Phishing; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/Pii.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | public class PII 10 | { 11 | public List Email { get; set; } 12 | public List IPA { get; set; } 13 | public List Phone { get; set; } 14 | public List
Address { get; set; } 15 | } 16 | 17 | public class PIIBase 18 | { 19 | public string Text { get; set; } 20 | public int Index { get; set; } 21 | } 22 | 23 | public class Email : PIIBase 24 | { 25 | public string Detected { get; set; } 26 | public string SubType { get; set; } 27 | } 28 | 29 | 30 | public class IPAddress : PIIBase 31 | { 32 | public string SubType { get; set; } 33 | } 34 | 35 | public class PhoneNumber : PIIBase 36 | { 37 | public string CountryCode { get; set; } 38 | } 39 | 40 | public class Address : PIIBase 41 | { 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/Result.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | public class Result 10 | { 11 | /// 12 | /// Status of the result 13 | /// 14 | public Status Status { get; set; } 15 | 16 | /// 17 | /// Tracking Id 18 | /// 19 | public string TrackingId { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/ScreenTextResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | /// 10 | /// Result from screening a text, containing details regarding the Match 11 | /// 12 | public class ScreenTextResult : Result 13 | { 14 | public string OriginalText; 15 | public string NormalizedText; 16 | public string Misrepresentation; 17 | public string Language; 18 | public MatchTerm[] Terms; 19 | public MatchUrl[] Urls; 20 | public PII PII; 21 | public string ContentId; 22 | public bool IsMatch; 23 | public MatchDetails MatchDetails; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Contract/Text/TermGetAllResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.CognitiveServices.ContentModerator.Contract.Text 8 | { 9 | public class TermGetAllResult 10 | { 11 | public TermsData Data { get; set; } 12 | } 13 | 14 | public class TermsData : Result 15 | { 16 | public string Language { get; set; } 17 | 18 | public List Terms { get; set; } 19 | } 20 | 21 | public class TermObject 22 | { 23 | public string Term { get; set; } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /ContentModeratorSDK/IListManagementClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 7 | 8 | namespace Microsoft.CognitiveServices.ContentModerator 9 | { 10 | using System.IO; 11 | using Microsoft.CognitiveServices.ContentModerator.Contract; 12 | using Microsoft.CognitiveServices.ContentModerator.Contract.Text; 13 | 14 | public interface IListManagementClient 15 | { 16 | #region Image API 17 | 18 | #region Image 19 | /// 20 | /// Add an image into the Image list 21 | /// 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | Task ImageAddAsync(string content, DataRepresentationType dataRepresentationType, string listId, string tag, 29 | string label); 30 | 31 | Task ImageAddAsync(Stream content, string listId, string tag, 32 | string label); 33 | 34 | /// 35 | /// Delete an image inside a listId. 36 | /// 37 | /// 38 | /// 39 | /// 40 | Task ImageDeleteAsync(string listId, string imageId); 41 | 42 | /// 43 | /// Deletes/Reset all images in a listId 44 | /// 45 | /// 46 | /// 47 | Task ImageDeleteAllAsync(string listId); 48 | 49 | /// 50 | /// Get List of all Image Ids in a list Id. 51 | /// 52 | /// 53 | Task ImageGetAllIdsAsync(string listId); 54 | 55 | #endregion 56 | 57 | #region ImageList 58 | /// 59 | /// Refresh index for a listId. 60 | /// 61 | /// 62 | /// 63 | Task ImageListRefreshIndexAsync(string listId); 64 | 65 | /// 66 | /// Get all the content lists 67 | /// 68 | /// 69 | Task> ImageListGetAllAsync(); 70 | 71 | /// 72 | /// Creates new list. 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | Task ImageListCreateAsync(string name, string description, Dictionary listMetaData); 79 | 80 | /// 81 | /// Updates the list details 82 | /// 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | Task ImageListUpdateAsync(string listId, string name, string description, Dictionary listMetaData); 89 | 90 | /// 91 | /// Get ListId details. 92 | /// 93 | /// 94 | /// 95 | Task ImageListDetailAsync(string listId); 96 | 97 | /// 98 | /// Deletes and image list. 99 | /// 100 | /// 101 | /// 102 | Task ImageListDeleteAsync(string listId); 103 | 104 | #endregion 105 | 106 | #endregion 107 | 108 | 109 | #region Text 110 | 111 | #region Term Management 112 | Task TermAddAsync(string listId, string term, string language); 113 | 114 | Task TermDeleteAsync(string listId, string term, string language); 115 | 116 | Task TermDeleteAllAsync(string listId, string language); 117 | 118 | Task TermGetAllTermsAsync(string listId, string language); 119 | 120 | #endregion 121 | 122 | #region Term Lists 123 | 124 | Task TermListRefreshIndexAsync(string listId, string language); 125 | 126 | /// 127 | /// Get all the content lists 128 | /// 129 | /// 130 | Task> TermListGetAllAsync(); 131 | 132 | /// 133 | /// Creates new list. 134 | /// 135 | /// 136 | /// 137 | /// 138 | /// 139 | Task TermListCreateAsync(string name, string description, Dictionary listMetaData); 140 | 141 | /// 142 | /// Updates the list details 143 | /// 144 | /// 145 | /// 146 | /// 147 | /// 148 | /// 149 | Task TermListUpdateAsync(string listId, string name, string description, Dictionary listMetaData); 150 | 151 | /// 152 | /// Get ListId details. 153 | /// 154 | /// 155 | /// 156 | Task TermListDetailAsync(string listId); 157 | 158 | /// 159 | /// Deletes and term list. 160 | /// 161 | /// 162 | /// 163 | Task TermListDeleteAsync(string listId); 164 | 165 | 166 | 167 | #endregion 168 | 169 | 170 | #endregion 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /ContentModeratorSDK/IModeratorClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 8 | using Microsoft.CognitiveServices.ContentModerator.Contract.Text; 9 | 10 | namespace Microsoft.CognitiveServices.ContentModerator 11 | { 12 | public interface IModeratorClient 13 | { 14 | /// 15 | /// Call Evaluate Image, to determine whether the image violates any policy based 16 | /// on multiple ratings. 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | Task EvaluateImageAsync(string content, DataRepresentationType dataRepresentationType, 23 | bool cacheImage); 24 | 25 | /// 26 | /// Call Evaluate Image, to determine whether the image violates any policy based 27 | /// on multiple ratings. 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | Task EvaluateImageAsync(Stream content, 34 | bool cacheImage); 35 | 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | /// 43 | Task DetectFacesImageAsync(string content, DataRepresentationType dataRepresentationType, 44 | bool cacheImage); 45 | 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | Task DetectFacesImageAsync(Stream content, 54 | bool cacheImage); 55 | 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | /// 65 | Task OCRImageAsync(string content, DataRepresentationType dataRepresentationType, 66 | bool cacheImage, bool enhanced = true, string language = "eng"); 67 | 68 | /// 69 | /// 70 | /// 71 | /// 72 | /// 73 | /// 74 | /// 75 | /// 76 | /// 77 | Task OCRImageAsync(Stream content, 78 | bool cacheImage, bool enhanced = true, string language = "eng"); 79 | 80 | /// 81 | /// Match an image against the images url provided. 82 | /// 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | Task MatchImageAsync(string content, DataRepresentationType dataRepresentationType, 89 | bool cacheImage, string listid); 90 | 91 | /// 92 | /// Match an image against the images stream provided. 93 | /// 94 | /// 95 | /// 96 | /// 97 | /// 98 | /// 99 | Task MatchImageAsync(Stream content, 100 | bool cacheImage, string listid); 101 | 102 | /// 103 | /// 104 | /// 105 | /// 106 | /// 107 | /// 108 | /// 109 | /// 110 | /// 111 | /// 112 | /// 113 | Task ScreenTextAsync(string content, Constants.MediaType mediaType, string language, 114 | bool autocorrect, bool urls, 115 | bool pii, string listIds); 116 | 117 | /// 118 | /// Identifies languange of the content passed 119 | /// 120 | /// 121 | /// 122 | /// 123 | Task IdentifyLanguageAsync(string content, Constants.MediaType mediaType); 124 | 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /ContentModeratorSDK/IReviewClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Microsoft.CognitiveServices.ContentModerator.Contract.Review; 8 | 9 | namespace Microsoft.CognitiveServices.ContentModerator 10 | { 11 | public interface IReviewClient 12 | { 13 | #region Review Operations 14 | /// 15 | /// Get review details for the review Id. 16 | /// 17 | /// 18 | /// 19 | /// 20 | Task GetReview(string teamName, string reviewId); 21 | 22 | /// 23 | /// Creates review. 24 | /// 25 | /// 26 | /// 27 | /// 28 | Task CreateReview(string teamName, List reviewRequests); 29 | 30 | #endregion 31 | 32 | #region Job Operations 33 | /// 34 | /// Get job details for the job Id. 35 | /// 36 | /// 37 | /// 38 | /// 39 | Task GetJobDetails(string teamName, string jobId); 40 | 41 | /// 42 | /// Creates a new Job based on url. 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | Task CreateJob(string teamName, string content, ContentType contentType, string contentId, string workFlowName, 52 | string callBackEndpoint); 53 | 54 | /// 55 | /// Creates a new Job based on image stream. 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | Task CreateJob(string teamName, Stream content, ContentType contentType, string contentId, string workFlowName, 65 | string callBackEndpoint); 66 | 67 | #endregion 68 | 69 | #region WorkFlow Operations 70 | 71 | /// 72 | /// Get all workflows of team. 73 | /// 74 | /// 75 | /// 76 | Task> GetAllWorkflows(string teamName); 77 | 78 | /// 79 | /// Get workflow details. 80 | /// 81 | /// 82 | /// 83 | /// 84 | Task GetWorkflow(string teamName, string workFlowName); 85 | 86 | /// 87 | /// Create new work flow. 88 | /// 89 | /// 90 | /// 91 | /// 92 | /// 93 | /// 94 | Task CreateWorkFlow(string teamName, string workFlowName, string description, Expression expression); 95 | 96 | #endregion 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ListManagementClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 10 | using Newtonsoft.Json; 11 | using Newtonsoft.Json.Serialization; 12 | 13 | namespace Microsoft.CognitiveServices.ContentModerator 14 | { 15 | using Microsoft.CognitiveServices.ContentModerator.Contract; 16 | using Microsoft.CognitiveServices.ContentModerator.Contract.Text; 17 | 18 | public class ListManagementClient : ClientBase, IListManagementClient 19 | { 20 | 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The subscription key. 26 | public ListManagementClient(string subscriptionKey) : this(subscriptionKey, "https://westus.api.cognitive.microsoft.com/contentmoderator/lists/v1.0") { } 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// The subscription key. 32 | /// Root URI for the service endpoint. 33 | public ListManagementClient(string subscriptionKey, string apiRoot) 34 | { 35 | this.ApiRoot = apiRoot?.TrimEnd('/'); 36 | this.SubscriptionKey = subscriptionKey; 37 | } 38 | 39 | #region ImageAPI 40 | 41 | #region Image Add 42 | public async Task ImageAddAsync(string content, DataRepresentationType dataRepresentationType, 43 | string listId, string tag, 44 | string label) 45 | { 46 | dynamic imageRequest = new ExpandoObject(); 47 | imageRequest.DataRepresentation = dataRepresentationType.ToString(); 48 | imageRequest.Value = content; 49 | 50 | var metaData = new List(); 51 | metaData.Add(new KeyValue() 52 | { 53 | Key = "tag", 54 | Value = tag 55 | }); 56 | metaData.Add(new KeyValue() 57 | { 58 | Key = "label", 59 | Value = label 60 | }); 61 | 62 | return 63 | await 64 | InvokeAsync( 65 | imageRequest, 66 | string.Format(Constants.IMAGE_ADD, listId), 67 | Constants.HttpMethod.POST, 68 | metaData); 69 | } 70 | 71 | public async Task ImageAddAsync(Stream content, string listId, string tag, string label) 72 | { 73 | dynamic imageRequest = new ExpandoObject(); 74 | imageRequest.Value = content; 75 | 76 | var metaData = new List(); 77 | metaData.Add(new KeyValue() 78 | { 79 | Key = "tag", 80 | Value = tag 81 | }); 82 | metaData.Add(new KeyValue() 83 | { 84 | Key = "label", 85 | Value = label 86 | }); 87 | 88 | 89 | return 90 | await 91 | InvokeAsync(imageRequest, 92 | string.Format(Constants.IMAGE_ADD, listId), Constants.HttpMethod.POST, metaData); 93 | } 94 | 95 | public async Task ImageGetAllIdsAsync(string listId) 96 | { 97 | return 98 | await this.InvokeAsync(string.Format(Constants.IMAGE_GETALLIDS, listId), Constants.HttpMethod.GET); 99 | } 100 | 101 | public async Task ImageDeleteAllAsync(string listId) 102 | { 103 | return 104 | await this.InvokeAsync( 105 | string.Format(Constants.IMAGE_DELETEALL, listId), 106 | Constants.HttpMethod.DELETE); 107 | } 108 | 109 | public async Task ImageDeleteAsync(string listId, string imageId) 110 | { 111 | return 112 | await this.InvokeAsync(string.Format(Constants.IMAGE_DELETE, listId, imageId), 113 | Constants.HttpMethod.DELETE); 114 | } 115 | #endregion 116 | 117 | #region ImageLists 118 | 119 | public async Task ImageListCreateAsync(string name, string description, 120 | Dictionary listMetaData) 121 | { 122 | dynamic imageListRequest = new ExpandoObject(); 123 | imageListRequest.Name = name; 124 | imageListRequest.Description = description; 125 | imageListRequest.Metadata = listMetaData; 126 | 127 | return 128 | await 129 | InvokeAsync( 130 | imageListRequest, 131 | Constants.IMAGELIST_CREATE, 132 | Constants.HttpMethod.POST); 133 | } 134 | 135 | public async Task ImageListUpdateAsync(string listId, string name, string description, 136 | Dictionary listMetaData) 137 | { 138 | dynamic imageListRequest = new ExpandoObject(); 139 | imageListRequest.Name = name; 140 | imageListRequest.Description = description; 141 | imageListRequest.Metadata = listMetaData; 142 | return 143 | await 144 | InvokeAsync( 145 | imageListRequest, 146 | string.Format(Constants.IMAGELIST_UPDATE, listId), 147 | Constants.HttpMethod.PUT); 148 | 149 | } 150 | 151 | public async Task ImageListRefreshIndexAsync(string listId) 152 | { 153 | dynamic imageRequest = new ExpandoObject(); 154 | return 155 | await 156 | InvokeAsync(imageRequest, 157 | string.Format(Constants.IMAGELIST_REFRESHINDEX, listId), Constants.HttpMethod.POST); 158 | 159 | } 160 | public async Task> ImageListGetAllAsync() 161 | { 162 | return 163 | await this.InvokeAsync>(Constants.IMAGELIST_GETALL, Constants.HttpMethod.GET, null); 164 | } 165 | public async Task ImageListDetailAsync(string listId) 166 | { 167 | return 168 | await this.InvokeAsync(string.Format(Constants.IMAGELIST_GETDETAIL, listId), 169 | Constants.HttpMethod.GET); 170 | } 171 | 172 | public async Task ImageListDeleteAsync(string listId) 173 | { 174 | 175 | return 176 | await this.InvokeAsync(string.Format(Constants.IMAGELIST_DELETE, listId), 177 | Constants.HttpMethod.DELETE); 178 | } 179 | 180 | public async Task TermAddAsync(string listId, string term, string language) 181 | { 182 | var metaData = new List 183 | { 184 | new KeyValue() 185 | { 186 | Key = "language", 187 | Value = language 188 | } 189 | }; 190 | 191 | await this.InvokeAsync( 192 | string.Format(Constants.TERM_ADD, listId, term), 193 | Constants.HttpMethod.POST, 194 | metaData); 195 | 196 | return string.Empty; 197 | 198 | } 199 | 200 | public async Task TermDeleteAsync(string listId, string term, string language) 201 | { 202 | var metaData = new List(); 203 | metaData.Add(new KeyValue() 204 | { 205 | Key = "language", 206 | Value = language 207 | }); 208 | 209 | 210 | await 211 | this.InvokeAsync( 212 | string.Format(Constants.TERM_DELETE, listId, term), 213 | Constants.HttpMethod.DELETE, 214 | metaData); 215 | 216 | return string.Empty; 217 | } 218 | 219 | public async Task TermDeleteAllAsync(string listId, string language) 220 | { 221 | var metaData = new List(); 222 | metaData.Add(new KeyValue() 223 | { 224 | Key = "language", 225 | Value = language 226 | }); 227 | 228 | await this.InvokeAsync(string.Format(Constants.TERM_DELETEALL, listId), Constants.HttpMethod.DELETE, metaData); 229 | 230 | return string.Empty; 231 | 232 | } 233 | 234 | public async Task TermGetAllTermsAsync(string listId, string language) 235 | { 236 | var metaData = new List 237 | { 238 | new KeyValue() 239 | { 240 | Key = "language", 241 | Value = language 242 | } 243 | }; 244 | 245 | 246 | return 247 | await this.InvokeAsync(string.Format(Constants.TERM_GETALLIDS, listId), Constants.HttpMethod.GET, metaData); 248 | } 249 | 250 | public async Task TermListRefreshIndexAsync(string listId, string language) 251 | { 252 | var metaData = new List 253 | { 254 | new KeyValue() 255 | { 256 | Key = "language", 257 | Value = language 258 | } 259 | }; 260 | 261 | await this.InvokeAsync(string.Format(Constants.TERMLIST_REFRESHINDEX, listId), Constants.HttpMethod.POST,metaData); 262 | 263 | return string.Empty; 264 | } 265 | 266 | public async Task> TermListGetAllAsync() 267 | { 268 | return 269 | await this.InvokeAsync>(Constants.TERMLIST_GETALL, Constants.HttpMethod.GET); 270 | } 271 | 272 | public async Task TermListCreateAsync(string name, string description, Dictionary listMetaData) 273 | { 274 | dynamic termlistrequest = new ExpandoObject(); 275 | termlistrequest.Name = name; 276 | termlistrequest.Description = description; 277 | termlistrequest.Metadata = listMetaData; 278 | 279 | return 280 | await 281 | InvokeAsync(termlistrequest, 282 | Constants.TERMLIST_CREATE, Constants.HttpMethod.POST); 283 | } 284 | 285 | public async Task TermListUpdateAsync(string listId, string name, string description, Dictionary listMetaData) 286 | { 287 | dynamic imageListRequest = new ExpandoObject(); 288 | imageListRequest.Name = name; 289 | imageListRequest.Description = description; 290 | imageListRequest.Metadata = listMetaData; 291 | 292 | return 293 | await 294 | InvokeAsync( 295 | imageListRequest, 296 | string.Format(Constants.TERMLIST_UPDATE, listId), 297 | Constants.HttpMethod.PUT); 298 | } 299 | 300 | public async Task TermListDetailAsync(string listId) 301 | { 302 | return 303 | await this.InvokeAsync(string.Format(Constants.TERMLIST_GETDETAIL, listId), 304 | Constants.HttpMethod.GET); 305 | } 306 | 307 | public async Task TermListDeleteAsync(string listId) 308 | { 309 | return 310 | await this.InvokeAsync(string.Format(Constants.TERMLIST_DELETE, listId), 311 | Constants.HttpMethod.DELETE); 312 | } 313 | 314 | #endregion 315 | 316 | #endregion 317 | 318 | #region Private methods 319 | 320 | 321 | 322 | 323 | 324 | 325 | #endregion 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ModeratorClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Microsoft.CognitiveServices.ContentModerator.Contract.Image; 10 | using Microsoft.CognitiveServices.ContentModerator.Contract.Text; 11 | using Newtonsoft.Json; 12 | using Newtonsoft.Json.Serialization; 13 | 14 | namespace Microsoft.CognitiveServices.ContentModerator 15 | { 16 | public class ModeratorClient : ClientBase, IModeratorClient 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The subscription key. 22 | public ModeratorClient(string subscriptionKey) : this(subscriptionKey, "https://westus.api.cognitive.microsoft.com/contentmoderator/moderate/v1.0") { } 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | /// The subscription key. 28 | /// Root URI for the service endpoint. 29 | public ModeratorClient(string subscriptionKey, string apiRoot) 30 | { 31 | this.ApiRoot = apiRoot?.TrimEnd('/'); 32 | this.SubscriptionKey = subscriptionKey; 33 | } 34 | 35 | #region EvaluateImage 36 | public async Task EvaluateImageAsync(string content, DataRepresentationType dataRepresentationType, bool cacheImage) 37 | { 38 | 39 | dynamic evaluateImageRequest = new ExpandoObject(); 40 | evaluateImageRequest.DataRepresentation = dataRepresentationType.ToString(); 41 | evaluateImageRequest.Value = content; 42 | 43 | List metaData = new List(); 44 | metaData.Add(new KeyValue() 45 | { 46 | Key = "CacheImage", 47 | Value = cacheImage.ToString() 48 | }); 49 | metaData.Add(new KeyValue() 50 | { 51 | Key = "subscription-key", 52 | Value = this.SubscriptionKey 53 | }); 54 | return await InvokeImageModeratorAsync(evaluateImageRequest, Constants.Operations.Evaluate.ToString(), metaData).ConfigureAwait(false); 55 | } 56 | 57 | public async Task EvaluateImageAsync(Stream content, bool cacheImage) 58 | { 59 | var imageType = ModeratorHelper.GetImageFormat(content); 60 | if (imageType.Equals(ModeratorHelper.ImageFormat.unknown)) 61 | { 62 | throw new Exception($"Image type: {imageType} not supported"); 63 | } 64 | content.Position = 0; 65 | 66 | List metaData = new List(); 67 | metaData.Add(new KeyValue() 68 | { 69 | Key = "CacheImage", 70 | Value = cacheImage.ToString() 71 | }); 72 | metaData.Add(new KeyValue() 73 | { 74 | Key = "subscription-key", 75 | Value = this.SubscriptionKey 76 | }); 77 | return await this.InvokeImageModeratorAsync(content, Constants.Operations.Evaluate.ToString(), metaData).ConfigureAwait(false); 78 | } 79 | 80 | #endregion 81 | 82 | #region DetectFaces 83 | public async Task DetectFacesImageAsync(string content, DataRepresentationType dataRepresentationType, bool cacheImage) 84 | { 85 | 86 | dynamic imageRequest = new ExpandoObject(); 87 | imageRequest.DataRepresentation = dataRepresentationType.ToString(); 88 | imageRequest.Value = content; 89 | 90 | List metaData = new List(); 91 | metaData.Add(new KeyValue() 92 | { 93 | Key = "CacheImage", 94 | Value = cacheImage.ToString() 95 | }); 96 | metaData.Add(new KeyValue() 97 | { 98 | Key = "subscription-key", 99 | Value = this.SubscriptionKey 100 | }); 101 | 102 | return await InvokeImageModeratorAsync(imageRequest, Constants.Operations.FindFaces.ToString(), metaData).ConfigureAwait(false); 103 | } 104 | 105 | public async Task DetectFacesImageAsync(Stream content, bool cacheImage) 106 | { 107 | var imageType = ModeratorHelper.GetImageFormat(content); 108 | if (imageType.Equals(ModeratorHelper.ImageFormat.unknown)) 109 | { 110 | throw new Exception($"Image type: {imageType} not supported"); 111 | } 112 | content.Position = 0; 113 | List metaData = new List(); 114 | metaData.Add(new KeyValue() 115 | { 116 | Key = "CacheImage", 117 | Value = cacheImage.ToString() 118 | }); 119 | 120 | return await this.InvokeImageModeratorAsync(content, Constants.Operations.FindFaces.ToString(), metaData).ConfigureAwait(false); 121 | } 122 | 123 | #endregion 124 | 125 | #region OCR 126 | public async Task OCRImageAsync(string content, DataRepresentationType dataRepresentationType, bool cacheImage, bool enhanced = true, string language = "eng") 127 | { 128 | 129 | dynamic imageRequest = new ExpandoObject(); 130 | imageRequest.DataRepresentation = dataRepresentationType.ToString(); 131 | imageRequest.Value = content; 132 | 133 | List metaData = new List(); 134 | metaData.Add(new KeyValue() 135 | { 136 | Key = "CacheImage", 137 | Value = cacheImage.ToString() 138 | }); 139 | metaData.Add(new KeyValue() 140 | { 141 | Key = "enhanced", 142 | Value = enhanced.ToString() 143 | }); 144 | metaData.Add(new KeyValue() 145 | { 146 | Key = "language", 147 | Value = language 148 | }); 149 | 150 | return 151 | await 152 | InvokeImageModeratorAsync(imageRequest, 153 | Constants.Operations.OCR.ToString(), metaData).ConfigureAwait(false); 154 | } 155 | 156 | public async Task OCRImageAsync(Stream content, bool cacheImage, bool enhanced = true, string language = "eng") 157 | { 158 | var imageType = ModeratorHelper.GetImageFormat(content); 159 | if (imageType.Equals(ModeratorHelper.ImageFormat.unknown)) 160 | { 161 | throw new Exception($"Image type: {imageType} not supported"); 162 | } 163 | content.Position = 0; 164 | List metaData = new List(); 165 | metaData.Add(new KeyValue() 166 | { 167 | Key = "CacheImage", 168 | Value = cacheImage.ToString() 169 | }); 170 | metaData.Add(new KeyValue() 171 | { 172 | Key = "enhanced", 173 | Value = enhanced.ToString() 174 | }); 175 | metaData.Add(new KeyValue() 176 | { 177 | Key = "language", 178 | Value = language 179 | }); 180 | 181 | return await this.InvokeImageModeratorAsync(content, Constants.Operations.OCR.ToString(), metaData).ConfigureAwait(false); 182 | } 183 | 184 | #endregion 185 | 186 | #region Match 187 | public async Task MatchImageAsync(string content, DataRepresentationType dataRepresentationType, 188 | bool cacheImage, string listid) 189 | { 190 | 191 | dynamic imageRequest = new ExpandoObject(); 192 | imageRequest.DataRepresentation = dataRepresentationType.ToString(); 193 | imageRequest.Value = content; 194 | 195 | List metaData = new List(); 196 | metaData.Add(new KeyValue() 197 | { 198 | Key = "CacheImage", 199 | Value = cacheImage.ToString() 200 | }); 201 | 202 | metaData.Add(new KeyValue() 203 | { 204 | Key = "listid", 205 | Value = listid 206 | }); 207 | 208 | return 209 | await 210 | InvokeImageModeratorAsync(imageRequest, 211 | Constants.Operations.Match.ToString(), metaData).ConfigureAwait(false); 212 | } 213 | 214 | public async Task MatchImageAsync(Stream content, bool cacheImage, string listid) 215 | { 216 | var imageType = ModeratorHelper.GetImageFormat(content); 217 | if (imageType.Equals(ModeratorHelper.ImageFormat.unknown)) 218 | { 219 | throw new Exception($"Image type: {imageType} not supported"); 220 | } 221 | content.Position = 0; 222 | List metaData = new List(); 223 | metaData.Add(new KeyValue() 224 | { 225 | Key = "CacheImage", 226 | Value = cacheImage.ToString() 227 | }); 228 | 229 | metaData.Add(new KeyValue() 230 | { 231 | Key = "listid", 232 | Value = listid 233 | }); 234 | 235 | return await this.InvokeImageModeratorAsync(content, Constants.Operations.Match.ToString(), metaData).ConfigureAwait(false); 236 | } 237 | 238 | #endregion 239 | 240 | #region Text 241 | 242 | public async Task ScreenTextAsync(string content, Constants.MediaType mediaType, 243 | string language, bool autocorrect, bool urls, bool pii, string listIds) 244 | { 245 | List metaData = new List(); 246 | metaData.Add(new KeyValue() 247 | { 248 | Key = "language", 249 | Value = language 250 | }); 251 | metaData.Add(new KeyValue() 252 | { 253 | Key = "autocorrect", 254 | Value = autocorrect.ToString() 255 | }); 256 | metaData.Add(new KeyValue() 257 | { 258 | Key = "urls", 259 | Value = urls.ToString() 260 | }); 261 | metaData.Add(new KeyValue() 262 | { 263 | Key = "PII", 264 | Value = pii.ToString() 265 | }); 266 | metaData.Add(new KeyValue() 267 | { 268 | Key = "listId", 269 | Value = listIds 270 | }); 271 | 272 | 273 | 274 | return 275 | await this.InvokeTextModeratorAsync(content, Constants.Operations.Screen.ToString(), 276 | mediaType,metaData); 277 | } 278 | 279 | 280 | public async Task IdentifyLanguageAsync(string content, Constants.MediaType mediaType) 281 | { 282 | return 283 | await this.InvokeTextModeratorAsync(content, Constants.Operations.DetectLanguage.ToString(), 284 | mediaType); 285 | } 286 | #endregion 287 | 288 | #region private methods 289 | 290 | private async Task InvokeImageModeratorAsync(dynamic imageRequest, string operation, List metaData = null) 291 | { 292 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, $"/ProcessImage/{operation}?")); 293 | 294 | if(metaData != null) 295 | foreach (var k in metaData) 296 | { 297 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 298 | requestUrl.Append("&"); 299 | } 300 | var request = WebRequest.Create(requestUrl.ToString()); 301 | 302 | return 303 | await 304 | this.SendAsync("POST", imageRequest, request) 305 | .ConfigureAwait(false); 306 | } 307 | 308 | private async Task InvokeTextModeratorAsync(dynamic textRequest, string operation, Constants.MediaType mediaType, List metaData = null) 309 | { 310 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, $"/ProcessText/{operation}?")); 311 | 312 | if(metaData != null) 313 | foreach (var k in metaData) 314 | { 315 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 316 | requestUrl.Append("&"); 317 | } 318 | var request = WebRequest.Create(requestUrl.ToString()); 319 | request.ContentType = ModeratorHelper.GetEnumDescription(mediaType); 320 | 321 | return 322 | await 323 | this.SendAsync("POST", textRequest, request) 324 | .ConfigureAwait(false); 325 | } 326 | 327 | #endregion 328 | 329 | 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ModeratorHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Microsoft.CognitiveServices.ContentModerator 11 | { 12 | public class ModeratorHelper 13 | { 14 | public enum ImageFormat 15 | { 16 | bmp, 17 | jpeg, 18 | gif, 19 | tiff, 20 | png, 21 | unknown 22 | } 23 | 24 | public static ImageFormat GetImageFormat(Stream stream) 25 | { 26 | // see http://www.mikekunz.com/image_file_header.html 27 | var bmp = Encoding.ASCII.GetBytes("BM"); // BMP 28 | var gif = Encoding.ASCII.GetBytes("GIF"); // GIF 29 | var png = new byte[] { 137, 80, 78, 71 }; // PNG 30 | var tiff = new byte[] { 73, 73, 42 }; // TIFF 31 | var tiff2 = new byte[] { 77, 77, 42 }; // TIFF 32 | var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg 33 | var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon 34 | 35 | var buffer = new byte[4]; 36 | stream.Read(buffer, 0, buffer.Length); 37 | 38 | if (bmp.SequenceEqual(buffer.Take(bmp.Length))) 39 | return ImageFormat.bmp; 40 | 41 | if (gif.SequenceEqual(buffer.Take(gif.Length))) 42 | return ImageFormat.gif; 43 | 44 | if (png.SequenceEqual(buffer.Take(png.Length))) 45 | return ImageFormat.png; 46 | 47 | if (tiff.SequenceEqual(buffer.Take(tiff.Length))) 48 | return ImageFormat.tiff; 49 | 50 | if (tiff2.SequenceEqual(buffer.Take(tiff2.Length))) 51 | return ImageFormat.tiff; 52 | 53 | if (jpeg.SequenceEqual(buffer.Take(jpeg.Length))) 54 | return ImageFormat.jpeg; 55 | 56 | if (jpeg2.SequenceEqual(buffer.Take(jpeg2.Length))) 57 | return ImageFormat.jpeg; 58 | 59 | return ImageFormat.unknown; 60 | } 61 | 62 | public static string GetEnumDescription(Enum value) 63 | { 64 | FieldInfo fi = value.GetType().GetField(value.ToString()); 65 | 66 | DescriptionAttribute[] attributes = 67 | (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); 68 | 69 | if (attributes != null && attributes.Length > 0) 70 | return attributes[0].Description; 71 | else 72 | return value.ToString(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ContentModeratorSDK/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ContentModeratorSDK_V2")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ContentModeratorSDK_V2")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("961284a5-1e23-416b-aba0-ff28c2327cab")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ContentModeratorSDK/ReviewClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Microsoft.CognitiveServices.ContentModerator.Contract.Review; 10 | using Newtonsoft.Json; 11 | using Newtonsoft.Json.Linq; 12 | using Newtonsoft.Json.Serialization; 13 | 14 | namespace Microsoft.CognitiveServices.ContentModerator 15 | { 16 | public class ReviewClient : ClientBase, IReviewClient 17 | { 18 | /// 19 | /// AD tenent url 20 | /// 21 | private const string DEFAULT_AD_TENANT_URL = "https://login.microsoftonline.com/contentmoderatorprod.onmicrosoft.com/oauth2/token"; 22 | 23 | /// 24 | /// AD tenent url 25 | /// 26 | private string DEFAULT_AD_REVIEW_SVC_URL = Uri.EscapeUriString("https://api.contentmoderator.cognitive.microsoft.com/review"); 27 | 28 | 29 | /// 30 | /// The client Id 31 | /// 32 | private string _clientId; 33 | 34 | /// 35 | /// The client secret 36 | /// 37 | private string _clientSecret; 38 | 39 | 40 | /// 41 | /// Initializes a new instance of the class. 42 | /// 43 | /// The subscription key. 44 | /// The client Id. 45 | /// The client secret. 46 | public ReviewClient(string subscriptionKey, string clientId, string clientSecret) : this(subscriptionKey, "https://westus.api.cognitive.microsoft.com/contentmoderator/review/v1.0", clientId, clientSecret) { } 47 | 48 | /// 49 | /// Initializes a new instance of the class. 50 | /// 51 | /// The subscription key. 52 | /// Root URI for the service endpoint. 53 | /// The client Id. 54 | /// The client secret. 55 | public ReviewClient(string subscriptionKey, string apiRoot, string clientId, string clientSecret) 56 | { 57 | this.ApiRoot = apiRoot?.TrimEnd('/'); 58 | this.SubscriptionKey = subscriptionKey; 59 | _clientId = clientId; 60 | _clientSecret = clientSecret; 61 | } 62 | 63 | #region Review Operations 64 | 65 | public async Task GetReview(string teamName, string reviewId) 66 | { 67 | List metaData = new List(); 68 | return 69 | await 70 | InvokeAsync(string.Format(Constants.GET_REVIEW_DETAILS, teamName, reviewId), 71 | Constants.HttpMethod.GET, metaData) 72 | .ConfigureAwait(false); 73 | } 74 | 75 | public async Task CreateReview(string teamName, List reviewRequests) 76 | { 77 | List metaData = new List(); 78 | return 79 | await 80 | InvokeAsync, string[]>(reviewRequests, 81 | string.Format(Constants.CREATE_REVIEW, teamName), Constants.HttpMethod.POST, metaData) 82 | .ConfigureAwait(false); 83 | } 84 | 85 | #endregion 86 | 87 | #region Job Operations 88 | 89 | public async Task GetJobDetails(string teamName, string jobId) 90 | { 91 | List metaData = new List(); 92 | return 93 | await 94 | InvokeAsync(string.Format(Constants.GET_JOB_DETAILS, teamName, jobId), 95 | Constants.HttpMethod.GET, metaData) 96 | .ConfigureAwait(false); 97 | } 98 | 99 | public async Task CreateJob(string teamName, string content, ContentType contentType, string contentId, 100 | string workFlowName, string callBackEndpoint) 101 | { 102 | dynamic jobRequest = new ExpandoObject(); 103 | jobRequest.ContentValue = content; 104 | 105 | List metaData = new List(); 106 | metaData.Add(new KeyValue() 107 | { 108 | Key = "ContentType", 109 | Value = contentType.ToString() 110 | }); 111 | 112 | metaData.Add(new KeyValue() 113 | { 114 | Key = "ContentId", 115 | Value = contentId 116 | }); 117 | 118 | metaData.Add(new KeyValue() 119 | { 120 | Key = "WorkflowName", 121 | Value = workFlowName 122 | }); 123 | 124 | metaData.Add(new KeyValue() 125 | { 126 | Key = "CallBackEndpoint", 127 | Value = callBackEndpoint 128 | }); 129 | 130 | return 131 | await 132 | InvokeAsync(jobRequest, 133 | string.Format(Constants.CREATE_JOB, teamName), Constants.HttpMethod.POST, metaData) 134 | .ConfigureAwait(false); 135 | } 136 | 137 | public async Task CreateJob(string teamName, Stream content, ContentType contentType, 138 | string contentId, string workFlowName, 139 | string callBackEndpoint) 140 | { 141 | var imageType = ModeratorHelper.GetImageFormat(content); 142 | if (imageType.Equals(ModeratorHelper.ImageFormat.unknown)) 143 | { 144 | throw new Exception($"Image type: {imageType} not supported"); 145 | } 146 | content.Position = 0; 147 | List metaData = new List(); 148 | metaData.Add(new KeyValue() 149 | { 150 | Key = "ContentType", 151 | Value = contentType.ToString() 152 | }); 153 | 154 | metaData.Add(new KeyValue() 155 | { 156 | Key = "ContentId", 157 | Value = contentId 158 | }); 159 | 160 | metaData.Add(new KeyValue() 161 | { 162 | Key = "WorkflowName", 163 | Value = workFlowName 164 | }); 165 | 166 | metaData.Add(new KeyValue() 167 | { 168 | Key = "CallBackEndpoint", 169 | Value = callBackEndpoint 170 | }); 171 | 172 | return 173 | await 174 | InvokeAsync(content, 175 | string.Format(Constants.CREATE_JOB, teamName), Constants.HttpMethod.POST, metaData) 176 | .ConfigureAwait(false); 177 | } 178 | 179 | #endregion 180 | 181 | #region Workflow Operations 182 | 183 | public async Task> GetAllWorkflows(string teamName) 184 | { 185 | List metaData = new List(); 186 | List workFlowList = new List(); 187 | 188 | JArray result = 189 | await 190 | InvokeAsync(string.Format(Constants.GET_ALL_TEAM_WORKFLOWS, teamName), 191 | Constants.HttpMethod.GET, metaData) 192 | .ConfigureAwait(false); 193 | 194 | if (result?.Count > 0) 195 | { 196 | List connectorNames = new List(); 197 | foreach (var wkf in result) 198 | { 199 | JObject wItem = wkf as JObject; 200 | WorkFlowItem item = new WorkFlowItem() 201 | { 202 | Name = wItem?["Name"].Value(), 203 | Description = wItem?["Description"].Value(), 204 | Expression = GetExpression(wItem?["Expression"] as JObject, connectorNames), 205 | }; 206 | workFlowList.Add(item); 207 | } 208 | } 209 | 210 | return workFlowList; 211 | } 212 | 213 | public async Task GetWorkflow(string teamName, string workFlowName) 214 | { 215 | List metaData = new List(); 216 | WorkFlowItem workFlowItem = null; 217 | JObject result = 218 | await 219 | InvokeAsync(string.Format(Constants.GET_TEAM_WORKFLOW, teamName, workFlowName), 220 | Constants.HttpMethod.GET, metaData) 221 | .ConfigureAwait(false); 222 | 223 | if (result != null) 224 | { 225 | List connectorNames = new List(); 226 | workFlowItem = new WorkFlowItem() 227 | { 228 | Name = result?["Name"].Value(), 229 | Description = result?["Description"].Value(), 230 | Expression = GetExpression(result?["Expression"] as JObject, connectorNames), 231 | }; 232 | } 233 | return workFlowItem; 234 | } 235 | 236 | public async Task CreateWorkFlow(string teamName, string workFlowName, string description, Expression expression) 237 | { 238 | dynamic workFlowRequest = new ExpandoObject(); 239 | workFlowRequest.Description = description; 240 | workFlowRequest.Expression = expression; 241 | 242 | await 243 | InvokeAsync(workFlowRequest, 244 | string.Format(Constants.CREATE_WORKFLOW, teamName, workFlowName), Constants.HttpMethod.PUT, 245 | new List()) 246 | .ConfigureAwait(false); 247 | 248 | return true; 249 | } 250 | 251 | #endregion 252 | 253 | #region Private methods 254 | 255 | private async Task GetToken() 256 | { 257 | string url = DEFAULT_AD_TENANT_URL; 258 | StringBuilder requestBody = new StringBuilder(); 259 | requestBody.Append(string.Concat("resource=", DEFAULT_AD_REVIEW_SVC_URL)); 260 | requestBody.Append(string.Concat("&client_id=", _clientId)); 261 | requestBody.Append(string.Concat("&client_secret=", _clientSecret)); 262 | requestBody.Append(string.Concat("&grant_type=", "client_credentials")); 263 | //string requestBody = 264 | // "resource=http%3A%2F%2Frvsvc&client_id=2c739b15-a26c-475e-b234-9bb366c2f70a&client_secret=cEKo9ocrj8apgRCgGuhpA96/SWcPUKTh1Z6NF40MBns=&grant_type=client_credentials"; 265 | var request = WebRequest.Create(url); 266 | return 267 | await 268 | this.SendAsync("POST", requestBody.ToString(), request, headerCallback) 269 | .ConfigureAwait(false); 270 | } 271 | private async Task InvokeAsync(dynamic imageRequest, string operationUrl, Constants.HttpMethod method, List metaData) 272 | { 273 | //Get Token 274 | var token = await GetToken(); 275 | 276 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, operationUrl, "?")); 277 | foreach (var k in metaData) 278 | { 279 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 280 | requestUrl.Append("&"); 281 | } 282 | requestUrl.Append(string.Concat("subscription-key=", this.SubscriptionKey, "&")); 283 | var request = WebRequest.Create(requestUrl.ToString()); 284 | request.Headers.Add("Authorization", string.Concat("Bearer ", token.access_token)); 285 | 286 | return 287 | await 288 | this.SendAsync(method.ToString(), imageRequest, request) 289 | .ConfigureAwait(false); 290 | } 291 | 292 | private async Task InvokeAsync(string operationUrl, Constants.HttpMethod method, List metaData) 293 | { 294 | //Get Token 295 | var token = await GetToken(); 296 | 297 | StringBuilder requestUrl = new StringBuilder(string.Concat(this.ApiRoot, operationUrl, "?")); 298 | foreach (var k in metaData) 299 | { 300 | requestUrl.Append(string.Concat(k.Key, "=", k.Value)); 301 | requestUrl.Append("&"); 302 | } 303 | 304 | requestUrl.Append(string.Concat("subscription-key=", this.SubscriptionKey, "&")); 305 | var request = WebRequest.Create(requestUrl.ToString()); 306 | 307 | request.Headers.Add("Authorization", string.Concat("Bearer ", token.access_token)); 308 | 309 | return 310 | await 311 | this.GetAsync(method.ToString(), request) 312 | .ConfigureAwait(false); 313 | } 314 | 315 | private void headerCallback(WebRequest request) 316 | { 317 | request.ContentType = "application/x-www-form-urlencoded"; 318 | } 319 | 320 | private static Expression GetExpression(JObject obj, List connectorNames) 321 | { 322 | Expression result = null; 323 | if (obj["Type"].Value() == "Combine") 324 | { 325 | var res = new Combination(); 326 | 327 | res.Left = GetExpression((JObject)obj["Left"], connectorNames); 328 | res.Right = GetExpression((JObject)obj["Right"], connectorNames); 329 | res.Combine = (CombineCondition)Enum.Parse(typeof(CombineCondition), obj["Combine"].Value()); 330 | result = res; 331 | } 332 | if (obj["Type"].Value() == "Condition") 333 | { 334 | result = JsonConvert.DeserializeObject(obj.ToString()); 335 | connectorNames.Add((result as Condition).ConnectorName); 336 | } 337 | 338 | return result; 339 | } 340 | #endregion 341 | 342 | 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /ContentModeratorSDK/nugetpackager/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftContentModerator/Microsoft.CognitiveServices.ContentModerator-Windows/38236497d16cb6020b55b91419610316adb9e49a/ContentModeratorSDK/nugetpackager/NuGet.exe -------------------------------------------------------------------------------- /ContentModeratorSDK/nugetpackager/Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.CognitiveServices.ContentModerator 5 | 1.1 6 | suraks@microsoft.com 7 | Microsoft 8 | false 9 | Microsoft.CognitiveServices.ContentModerator 10 | ContentModeratorSDK 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ContentModeratorSDK/nugetpackager/PostBuildCommand.bat: -------------------------------------------------------------------------------- 1 | copy nugetpackager\NuGet.exe %4 2 | copy nugetpackager\Package.nuspec %4 3 | md %4content\%2\ 4 | copy %1 %4content\%2\ 5 | %9nuget pack 6 | echo y | del %4content\%2\*.* -------------------------------------------------------------------------------- /ContentModeratorSDK/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE-IMAGE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation 2 | 3 | All rights reserved. 4 | 5 | Microsoft Cognitive Services Client SDK License for Sample Image 6 | 7 | *This license applies only to the sample images. The SDK code is licensed separately, please refer to [LICENSE]()* 8 | 9 | Microsoft may make sample images available in connection with the SDK for the purposes of illustrating the operation of Microsoft Cognitive Services (https://www.microsoft.com/cognitive-services). If no separate license terms are provided with the images, Microsoft grants you a personal, nonexclusive, revocable, royalty-free right to use the images solely within your organization to test the operation of Microsoft Cognitive Services, provided that you agree to indemnify, hold harmless, and defend Microsoft and its suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the images. Except as expressly provided in this section you have no license to modify or distribute the images. 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Microsoft Cognitive Services SDK 2 | 3 | Copyright (c) Microsoft Corporation 4 | 5 | All rights reserved. 6 | 7 | *This license applies only to the SDK code. Sample images are licensed separately, please refer to [LICENSE-IMAGE]()* 8 | 9 | MIT License 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microsoft Content Moderator API: Windows Client Library 2 | This repo contains the Windows client library & sample for the Microsoft Content Moderator API, part of [Microsoft Cognitive Services](https://azure.microsoft.com/en-us/services/cognitive-services/). 3 | * [Learn about the Content Moderator](https://azure.microsoft.com/en-us/services/cognitive-services/content-moderator/) 4 | * [Read the documentation](https://docs.microsoft.com/en-us/azure/cognitive-services/content-moderator/overview) 5 | 6 | 7 | ## The Client Library 8 | The client library is a thin C\# client wrapper for the Content Moderator API. 9 | 10 | ### Build the Library 11 | 1. Starting in the folder where you clone the repository (this folder) 12 | 13 | 3. Start Microsoft Visual Studio 2015 and select `File > Open > Project/Solution`. 14 | 15 | 4. Double-click the Visual Studio 2015 Solution (.sln) file. 16 | 17 | 5. Press Ctrl+Shift+B, or select `Build > Build Solution`. 18 | 19 | You run the Unit Tests to test the Client Library. 20 | 21 | 22 | Microsoft will receive the images you upload and may use them to improve the Content Moderator 23 | API and related services. By submitting an image, you confirm you have consent from everyone in it. 24 | 25 | ## Contributing 26 | We welcome contributions. Feel free to file issues and pull requests on the repo and we'll address them as we can. Learn more about how you can help on our [Contribution Rules & Guidelines](). 27 | 28 | You can reach out to us anytime with questions and suggestions using our communities below: 29 | - **Feedback & feature requests:** [Cognitive Services UserVoice Forum]() 30 | 31 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 32 | 33 | 34 | ## License 35 | All Microsoft Cognitive Services SDKs and samples are licensed with the MIT License. For more details, see 36 | [LICENSE](). 37 | 38 | Sample images are licensed separately, please refer to [LICENSE-IMAGE](). 39 | 40 | 41 | ## Developer Code of Conduct 42 | Developers using Cognitive Services, including this client library & sample, are expected to follow the “Developer Code of Conduct for Microsoft Cognitive Services”, found at [http://go.microsoft.com/fwlink/?LinkId=698895](http://go.microsoft.com/fwlink/?LinkId=698895). 43 | -------------------------------------------------------------------------------- /ThirdPartyNotices.txt: -------------------------------------------------------------------------------- 1 | THIRD-PARTY SOFTWARE NOTICES AND INFORMATION 2 | Do Not Translate or Localize 3 | 4 | This project incorporates components from the projects listed below. The original copyright notices 5 | and licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not 6 | expressly granted herein, whether by implication, estoppel or otherwise. 7 | 8 | 9 | 1. newtonsoft.json version 8.0.2 (https://github.com/JamesNK/Newtonsoft.Json) 10 | 11 | %% newtonsoft.json NOTICES AND INFORMATION BEGIN HERE 12 | ========================================= 13 | The MIT License (MIT) 14 | 15 | Copyright (c) 2007 James Newton-King 16 | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy of 18 | this software and associated documentation files (the "Software"), to deal in 19 | the Software without restriction, including without limitation the rights to 20 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 21 | the Software, and to permit persons to whom the Software is furnished to do so, 22 | subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in all 25 | copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 29 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 30 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 31 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | ========================================= 34 | END OF newtonsoft.json NOTICES AND INFORMATION 35 | --------------------------------------------------------------------------------