< Summary

Class:BuilderAPIController
Assembly:BuilderAPI
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/BuilderInWorld/Scripts/BuiilderAPI/BuilderAPIController.cs
Covered lines:67
Uncovered lines:106
Coverable lines:173
Total lines:384
Line coverage:38.7% (67 of 173)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
BuilderAPIController()0%110100%
Initialize(...)0%2.032080%
Dispose()0%2.152066.67%
AskHeadersToKernel(...)0%3.033085.71%
HeadersReceived(...)0%550100%
CallUrl(...)0%110100%
CallWeb()0%56700%
SetManifest(...)0%2100%
SetThumbnail(...)0%2100%
GetManifestById(...)0%2100%
CreateNewProject(...)0%2100%
GetCompleteCatalog(...)0%110100%
GetAssets(...)0%6.755058.82%
GetAllManifests()0%110100%
GetManifestFromProjectId(...)0%2100%
GetManifestFromLandCoordinates(...)0%2100%
UpdateProjectManifest(...)0%2100%
CreateEmptyProjectWithCoords(...)0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/BuilderInWorld/Scripts/BuiilderAPI/BuilderAPIController.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using System.Net;
 6using System.Net.Http;
 7using DCL;
 8using DCL.Builder;
 9using DCL.Builder.Manifest;
 10using DCL.Helpers;
 11using Newtonsoft.Json;
 12using Newtonsoft.Json.Linq;
 13using UnityEngine;
 14using UnityEngine.Networking;
 15using UnityEngine.SocialPlatforms.Impl;
 16
 17public class BuilderAPIController : IBuilderAPIController
 18{
 19    internal const string API_DATEFORMAT = "yyyy-MM-ddThh:mm:ss.fff%K";
 20
 21    internal const string CATALOG_ENDPOINT = "/assetPacks";
 22    internal const string ASSETS_ENDPOINT = "/assets?";
 23    internal const string GET_PROJECTS_ENDPOINT = "/projects";
 24    internal const string PROJECT_MANIFEST_ENDPOINT = "/projects/{ID}/manifest";
 25    internal const string PROJECT_THUMBNAIL_ENDPOINT = "/projects/{ID}/media";
 26
 27    internal const string API_KO_RESPONSE_ERROR = "API response is KO";
 28
 29    internal const string GET = "get";
 30    internal const string PUT = "put";
 31    internal const string POST = "post";
 32
 33    public event Action<IWebRequestAsyncOperation> OnWebRequestCreated;
 34
 35    internal IBuilderAPIResponseResolver apiResponseResolver;
 36
 37    private BuilderInWorldBridge builderInWorldBridge;
 38
 439    private Dictionary<string, List<Promise<RequestHeader>>> headersRequests = new Dictionary<string, List<Promise<Reque
 40
 41    public void Initialize(IContext context)
 42    {
 443        apiResponseResolver = new BuilderAPIResponseResolver();
 444        builderInWorldBridge = context.sceneReferences.biwBridgeGameObject.GetComponent<BuilderInWorldBridge>();
 445        if (builderInWorldBridge != null)
 046            builderInWorldBridge.OnHeadersReceived += HeadersReceived;
 447    }
 48
 49    public void Dispose()
 50    {
 451        if (builderInWorldBridge != null)
 052            builderInWorldBridge.OnHeadersReceived -= HeadersReceived;
 453    }
 54
 55    internal Promise<RequestHeader> AskHeadersToKernel(string method, string endpoint)
 56    {
 557        Promise<RequestHeader> promise = new Promise<RequestHeader>();
 558        if (headersRequests.ContainsKey(endpoint))
 159            headersRequests[endpoint].Add(promise);
 60        else
 461            headersRequests.Add(endpoint, new List<Promise<RequestHeader>>() { promise });
 62
 563        if (builderInWorldBridge != null)
 064            builderInWorldBridge.AskKernelForCatalogHeadersWithParams(method, endpoint);
 565        return promise;
 66    }
 67
 68    internal void HeadersReceived(RequestHeader requestHeader)
 69    {
 570        string keyToRemove = "";
 1871        foreach (var request in headersRequests)
 72        {
 473            if (request.Key == requestHeader.endpoint)
 74            {
 475                keyToRemove = request.Key;
 1876                foreach (Promise<RequestHeader> promise in request.Value)
 77                {
 578                    promise.Resolve(requestHeader);
 79                }
 80            }
 81        }
 82
 583        if (headersRequests.ContainsKey(keyToRemove))
 484            headersRequests.Remove(keyToRemove);
 585    }
 86
 87    internal Promise<string> CallUrl(string method, string endpoint, string callParams = "", byte[] body = null, string 
 88    {
 489        Promise<string> resultPromise = new Promise<string>();
 490        Promise<RequestHeader> headersPromise = AskHeadersToKernel(method, endpoint);
 491        headersPromise.Then(request =>
 92        {
 93            switch (method)
 94            {
 95                case GET:
 496                    IWebRequestAsyncOperation webRequest = BIWUtils.MakeGetCall(BIWUrlUtils.GetBuilderAPIBaseUrl() + req
 497                    OnWebRequestCreated?.Invoke(webRequest);
 098                    break;
 99                case PUT:
 0100                    request.body = body;
 0101                    CoroutineStarter.Start(CallWeb(request, resultPromise, contentType));
 0102                    break;
 103                case POST:
 0104                    request.body = body;
 0105                    CoroutineStarter.Start(CallWeb(request, resultPromise, contentType, false));
 106                    break;
 107            }
 0108        });
 109
 4110        return resultPromise;
 111    }
 112
 113    //This will disappear when we implement the signed fetch call
 114    IEnumerator CallWeb (RequestHeader requestHeader, Promise<string> resultPromise, string contentType, bool isPut = tr
 115    {
 0116        UnityWebRequest www = null;
 0117        if (isPut)
 0118            www = UnityWebRequest.Put (BIWUrlUtils.GetBuilderAPIBaseUrl() + requestHeader.endpoint, requestHeader.body);
 119        else
 120        {
 0121            WWWForm form = new WWWForm();
 0122            form.AddBinaryData("thumbnail", requestHeader.body);
 0123            www = UnityWebRequest.Post(BIWUrlUtils.GetBuilderAPIBaseUrl() + requestHeader.endpoint, form );
 124        }
 125
 0126        if (!string.IsNullOrEmpty(contentType))
 0127            www.SetRequestHeader("Content-Type", contentType);
 128
 0129        foreach (var header in requestHeader.headers)
 130        {
 0131            www.SetRequestHeader(header.Key, header.Value);
 132        }
 133
 0134        yield return www.SendWebRequest();
 135
 0136        if (www.result != UnityWebRequest.Result.Success)
 137        {
 0138            resultPromise.Reject(www.error);
 0139        }
 140        else
 141        {
 0142            byte[] byteArray = www.downloadHandler.data;
 0143            string result = System.Text.Encoding.UTF8.GetString(byteArray);
 0144            resultPromise.Resolve(result);
 145        }
 146
 0147    }
 148
 149    public Promise<bool> SetManifest(Manifest manifest)
 150    {
 0151        Promise<bool> fullPromise = new Promise<bool>();
 152
 0153        JsonSerializerSettings dateFormatSettings = new JsonSerializerSettings
 154        {
 155            DateFormatString = API_DATEFORMAT,
 156        };
 157
 0158        string jsonManifest = JsonConvert.SerializeObject(manifest, dateFormatSettings);
 159
 0160        byte[] myData = System.Text.Encoding.UTF8.GetBytes(BIWUrlUtils.GetManifestJSON(jsonManifest));
 161
 0162        string endpoint = PROJECT_MANIFEST_ENDPOINT.Replace("{ID}", manifest.project.id);
 0163        var promise =  CallUrl(PUT, endpoint, "", myData, "application/json");
 164
 0165        promise.Then(result =>
 166        {
 0167            var apiResponse = apiResponseResolver.GetResponseFromCall(result);
 0168            if (apiResponse.ok)
 0169                fullPromise.Resolve(true);
 170            else
 0171                fullPromise.Reject(apiResponse.error);
 0172        });
 173
 0174        promise.Catch(error =>
 175        {
 0176            fullPromise.Reject(error);
 0177        });
 178
 0179        return fullPromise;
 180    }
 181
 182    public Promise<bool> SetThumbnail(string id, Texture2D thumbnail)
 183    {
 0184        Promise<bool> fullPromise = new Promise<bool>();
 185
 0186        byte[] myData = thumbnail.EncodeToPNG();
 187
 0188        string endpoint = PROJECT_THUMBNAIL_ENDPOINT.Replace("{ID}", id);
 0189        var promise =  CallUrl(POST, endpoint, "", myData);
 190
 0191        promise.Then(result =>
 192        {
 0193            var apiResponse = apiResponseResolver.GetResponseFromCall(result);
 0194            if (apiResponse.ok)
 0195                fullPromise.Resolve(true);
 196            else
 0197                fullPromise.Reject(apiResponse.error);
 0198        });
 199
 0200        promise.Catch(error =>
 201        {
 0202            fullPromise.Reject(error);
 0203        });
 204
 0205        return fullPromise;
 206    }
 207
 208    public Promise<Manifest> GetManifestById(string idProject)
 209    {
 0210        Promise<Manifest> fullNewProjectPromise = new Promise<Manifest>();
 211
 0212        string url = PROJECT_MANIFEST_ENDPOINT.Replace("{ID}", idProject);
 0213        var promise =  CallUrl(GET, url);
 214
 0215        promise.Then(result =>
 216        {
 0217            Manifest manifest = null;
 218
 219            try
 220            {
 0221                manifest = JsonConvert.DeserializeObject<Manifest>(result);
 0222            }
 0223            catch (Exception e)
 224            {
 0225                fullNewProjectPromise.Reject(e.Message);
 0226                return;
 227            }
 228
 0229            fullNewProjectPromise.Resolve(manifest);
 0230        });
 0231        promise.Catch(error =>
 232        {
 0233            fullNewProjectPromise.Reject(error);
 0234        });
 0235        return fullNewProjectPromise;
 236    }
 237
 238    public Promise<Manifest> CreateNewProject(ProjectData newProject)
 239    {
 0240        Promise<Manifest> fullNewProjectPromise = new Promise<Manifest>();
 0241        Manifest builderManifest = BIWUtils.CreateManifestFromProject(newProject);
 242
 0243        JsonSerializerSettings dateFormatSettings = new JsonSerializerSettings
 244        {
 245            DateFormatString = API_DATEFORMAT,
 246        };
 247
 0248        string jsonManifest = JsonConvert.SerializeObject(builderManifest, dateFormatSettings);
 0249        byte[] myData = System.Text.Encoding.UTF8.GetBytes(BIWUrlUtils.GetManifestJSON(jsonManifest));
 250
 0251        string endpoint = PROJECT_MANIFEST_ENDPOINT.Replace("{ID}", newProject.id);
 0252        var promise =  CallUrl(PUT, endpoint, "", myData, "application/json");
 253
 0254        promise.Then(result =>
 255        {
 0256            var apiResponse = apiResponseResolver.GetResponseFromCall(result);
 0257            if (apiResponse.ok)
 0258                fullNewProjectPromise.Resolve((Manifest)apiResponse.data);
 259            else
 0260                fullNewProjectPromise.Reject(apiResponse.error);
 0261        });
 262
 0263        promise.Catch(error =>
 264        {
 0265            fullNewProjectPromise.Reject(error);
 0266        });
 267
 0268        return fullNewProjectPromise;
 269    }
 270
 271    public Promise<bool> GetCompleteCatalog(string ethAddres)
 272    {
 1273        Promise<bool> fullCatalogPromise = new Promise<bool>();
 274
 1275        var promiseDefaultCatalog =  CallUrl(GET, CATALOG_ENDPOINT, "?owner=default");
 1276        var promiseOwnedCatalog = CallUrl(GET, CATALOG_ENDPOINT, "?owner=" + ethAddres);
 1277        int amountOfCatalogReceived = 0;
 278
 279        // Note: In order to get the full catalog we need to do 2 calls, the default one and the specific one
 280        // This is done in order to cache the response in the server
 1281        promiseDefaultCatalog.Then(catalogJson =>
 282        {
 1283            AssetCatalogBridge.i.AddFullSceneObjectCatalog(catalogJson);
 284
 1285            amountOfCatalogReceived++;
 1286            if (amountOfCatalogReceived >= 2)
 0287                fullCatalogPromise.Resolve(true);
 1288        });
 1289        promiseDefaultCatalog.Reject("Unable to get default catalog");
 290
 1291        promiseOwnedCatalog.Then(catalogJson =>
 292        {
 1293            AssetCatalogBridge.i.AddFullSceneObjectCatalog(catalogJson);
 294
 1295            amountOfCatalogReceived++;
 1296            if (amountOfCatalogReceived >= 2)
 1297                fullCatalogPromise.Resolve(true);
 1298        });
 299
 1300        promiseOwnedCatalog.Reject("Unable to get owned catalog");
 301
 1302        return fullCatalogPromise;
 303    }
 304
 305    public Promise<bool> GetAssets(List<string> assetsIds)
 306    {
 1307        List<string> assetsToAsk = new List<string>();
 2308        foreach (string assetsId in assetsIds)
 309        {
 0310            if (!AssetCatalogBridge.i.sceneObjectCatalog.ContainsKey(assetsId))
 0311                assetsToAsk.Add(assetsId);
 312        }
 313
 1314        string query = "";
 2315        foreach (string assetsId in assetsToAsk)
 316        {
 0317            if (string.IsNullOrEmpty(query))
 0318                query += "id=" + assetsId;
 319            else
 0320                query += "&id=" + assetsId;
 321        }
 322
 1323        Promise<bool> fullCatalogPromise = new Promise<bool>();
 324
 1325        var promise =  CallUrl(GET, ASSETS_ENDPOINT , query);
 326
 1327        promise.Then(apiResult =>
 328        {
 1329            var assets = apiResponseResolver.GetArrayFromCall<SceneObject>(apiResult);
 1330            if (assets != null)
 331            {
 1332                AssetCatalogBridge.i.AddScenesObjectToSceneCatalog(assets);
 1333                fullCatalogPromise.Resolve(true);
 1334            }
 335            else
 336            {
 0337                fullCatalogPromise.Reject(API_KO_RESPONSE_ERROR);
 338            }
 0339        });
 340
 1341        return fullCatalogPromise;
 342    }
 343
 344    public Promise<List<ProjectData>> GetAllManifests()
 345    {
 1346        Promise<List<ProjectData>> fullCatalogPromise = new Promise< List<ProjectData>>();
 347
 1348        var promise =  CallUrl(GET, GET_PROJECTS_ENDPOINT);
 349
 1350        promise.Then(result =>
 351        {
 1352            List<ProjectData> allManifest = apiResponseResolver.GetArrayFromCall<ProjectData>(result).ToList();
 1353            fullCatalogPromise.Resolve(allManifest);
 1354        });
 1355        promise.Catch(error =>
 356        {
 0357            fullCatalogPromise.Reject(error);
 0358        });
 1359        return fullCatalogPromise;
 360    }
 361
 362    public Manifest GetManifestFromProjectId(string projectId)
 363    {
 364        //TODO: Implement functionality
 0365        return null;
 366    }
 367
 368    public Manifest GetManifestFromLandCoordinates(string landCoords)
 369    {
 370        //TODO: Implement functionality
 0371        return null;
 372    }
 373
 374    public void UpdateProjectManifest(Manifest manifest)
 375    {
 376        //TODO: Implement functionality
 0377    }
 378
 379    public void CreateEmptyProjectWithCoords(string coords)
 380    {
 0381        Manifest manifest = BIWUtils.CreateEmptyDefaultBuilderManifest(coords);
 382        //TODO: Implement functionality
 0383    }
 384}