示例#1
0
        public IEnumerator AddItemRoutine(string item)
        {
            string uuid = System.Guid.NewGuid().ToString();
            string body = JsonBody.TodoistTask(item, projectId);

            UnityWebRequest request = Postman.CreatePostRequest(Endpoints.instance.TODOIST_TASKS(), body);

            request.SetRequestHeader("Authorization", "Bearer " + apiKey);
            request.SetRequestHeader("X-Request-Id", uuid);
            yield return(request.SendWebRequest());

            bool ok = request.error == null ? true : false;

            if (!ok)
            {
                WidgetLogger.instance.Log("<b>" + listType.ToString() + " List</b>: Could not add item (" + item + "): " + request.downloadHandler.text);
                itemsNotUploaded.Add(item);

                // Todoist is flaky, and to avoid messing up category order, try again immediately
                if (request.responseCode == 500)
                {
                    yield return(AddItemRoutine(item));
                }
            }
            else if (itemsNotUploaded.Contains(item))
            {
                itemsNotUploaded.Remove(item);
            }

            addDialog.SetStatusText(string.Format("'{0}' uploaded!", item));
        }
示例#2
0
        public void RenderWithArray_ShouldParseAsJArrayObject()
        {
            var bodyArray = new[] { "value1", "value2" };
            var jBody     = new JsonBody(bodyArray);

            jBody.Render().Should().BeOfType <JArray>()
            .Which.Count.Should().Be(bodyArray.Length);
        }
示例#3
0
        public void TestJsonBody()
        {
            JsonBody body = new JsonBody();

            Assert.Null(body.GetBody());
            body.AddParameter(new { id = 1 });
            Assert.True(body.GetBody().Length > 0);
        }
示例#4
0
        public static async Task <HttpResponseMessage> PostJsonAsync <T>(
            this ICateHttp cate, string uri, T data)
        {
            var body = new JsonBody(cate
                                    .Configuration.JsonSerializer.Serialize(data));

            return(await cate.SendAsync(uri, HttpMethod.Post, MimeType.Json, body));
        }
示例#5
0
        public void RenderWithObject_ShouldCreateAJObject()
        {
            var jObject = new { prop1 = "value1" };
            var jBody   = new JsonBody(jObject);

            jBody.Render()
            .Should().BeOfType <JObject>()
            .Which.ContainsKey("prop1").Should().BeTrue();
        }
示例#6
0
    public void PostMessage(string text)
    {
        JsonBody payload = new JsonBody()
        {
            Text = text
        };

        PostMessage(payload);
    }
示例#7
0
        public void RenderWithString_ShouldParseAsJsonObject()
        {
            var jsonObjectString = @"{ prop1: 'value' }";
            var jBody            = new JsonBody(jsonObjectString);

            jBody.Render()
            .Should().BeOfType <JObject>()
            .Which.ContainsKey("prop1").Should().BeTrue();
        }
示例#8
0
        public void RenderWithIJsonable_ShouldCallRenderMethodOfBody()
        {
            var iJsonableMock = new Mock <IJsonable>();
            var jBody         = new JsonBody(iJsonableMock.Object);

            jBody.Render();

            iJsonableMock.Verify(x => x.Render(), Times.Once());
        }
        /// <summary>
        /// 设置json数据
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public INoneBodyBuilder Body(object parameters)
        {
            var body = new JsonBody();

            body.AddParameter(parameters);
            _requestBody = body;
            ContentType("application/json");
            return(this);
        }
示例#10
0
        public string ToJson(bool formatted = false)
        {
            var body = new JsonBody();

            body.Name      = Name;
            body.Arguments = Arguments?.ToJson();

            return(JsonSerializer.Serialize(body, new JsonSerializerOptions {
                WriteIndented = formatted, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            }));
        }
示例#11
0
        public void RenderWithIEnumerable_ShouldParseAsJArrayObject()
        {
            var bodyArray = new List <string> {
                "value1", "value2"
            }.AsEnumerable();
            var jBody = new JsonBody(bodyArray);

            jBody.Render()
            .Should().BeOfType <JArray>()
            .Which.Count.Should().Be(2);
        }
示例#12
0
        public IActionResult Update(long id, JsonBody body)
        {
            string decision = body.decision;

            BadDecision toBeModified = new BadDecision()
            {
                Id       = id,
                Decision = decision
            };
            BadDecision modified = _badDecisionRepository.Update(toBeModified);

            return(Ok(toBeModified));
        }
示例#13
0
    public void PostMessage(JsonBody payload)
    {
        string payloadJson = JsonConvert.SerializeObject(payload);

        using (WebClient client = new WebClient())
        {
            NameValueCollection data = new NameValueCollection();
            data["payload"] = payloadJson;

            var response = client.UploadValues(_uri, "POST", data);

            string responseText = _encoding.GetString(response);
        }
    }
示例#14
0
        public ExceptionResponse(System.Exception exception)
        {
            if (exception == null)
            {
                throw new System.ArgumentNullException(nameof(exception));
            }

            ResponseStatusCode = 500;
            ResponseHeaders.Add("Exception-Type", exception.GetType().ToString());
            ResponseHeaders.Add("Exception-Message", exception.Message);
            ResponseHeaders.Add("Content-Type", "application/json; charset=utf-8");
            ResponseBody = new JsonBody(new
            {
                Message    = exception.Message,
                Type       = exception.GetType(),
                StackTrace = exception.StackTrace
            });
        }
示例#15
0
        private IEnumerator ClearRecipeRoutine()
        {
            JSONObject      body    = JsonBody.AddToPlanner(" ", day.ToString());
            UnityWebRequest request = Postman.CreatePostRequest(Endpoints.instance.PLANNER(), body);

            yield return(request.SendWebRequest());

            JSONNode response = JSON.Parse(request.downloadHandler.text);

            if (request.error == null)
            {
                recipe.text = "";
            }
            else
            {
                WidgetLogger.instance.Log("Could not clear recipe: " + response["message"]);
            }
        }
示例#16
0
        public IActionResult Create(JsonBody body)
        {
            List <BadDecision> decisions = _badDecisionRepository.GetAll();
            string             decision  = body.decision;

            BadDecision badDecision = new BadDecision()
            {
                Id       = decisions.Count + 1,
                Decision = decision
            };

            BadDecision newDecision = _badDecisionRepository.Create(badDecision);

            if (newDecision == null)
            {
                return(BadRequest());
            }
            return(Ok(newDecision));
        }
示例#17
0
        private IEnumerator UploadNewRecipeRoutine()
        {
            NewIngredientEntry[] newIngredients = FindObjectsOfType <NewIngredientEntry>();

            JSONArray ingredientsArray = new JSONArray();

            foreach (NewIngredientEntry newIngredient in newIngredients)
            {
                JSONObject ingredientJson = JsonBody.RecipeIngredient(newIngredient.GetIngredientName(), newIngredient.GetAmount(), newIngredient.GetWeight(), newIngredient.GetCategory());
                ingredientsArray.Add(ingredientJson);
            }

            JSONObject body = JsonBody.AddRecipe(recipeName.text, ingredientsArray);

            UnityWebRequest request = Postman.CreatePostRequest(Endpoints.instance.RECIPES(), body);

            yield return(request.SendWebRequest());

            status.text = request.responseCode.Equals(200) ? recipeName.text + " added!" : "Error: " + request.error;
        }
示例#18
0
        public IEnumerator SelectRecipeRoutine()
        {
            RecipeSelectionDialog dialog = FindObjectOfType <RecipeSelectionDialog>();

            dialog.Show();
            dialog.SetNone();
            dialog.PopulateRecipes();

            while (!dialog.IsFinished() && !dialog.IsCancel())
            {
                yield return(null);
            }

            if (dialog.IsFinished())
            {
                recipe.text = !string.IsNullOrEmpty(dialog.GetSelectedRecipe()) ? dialog.GetSelectedRecipe() : dialog.GetFreeTextRecipeName();
                string          recipeName = string.IsNullOrEmpty(recipe.text) ? " " : recipe.text;
                JSONObject      body       = JsonBody.AddToPlanner(recipeName, day.ToString());
                UnityWebRequest request    = Postman.CreatePutRequest(Endpoints.instance.PLANNER(), body.ToString());
                yield return(request.SendWebRequest());

                yield break;
            }
        }
        public HttpRequestMessage Build()
        {
            var httpMessage = new HttpRequestMessage(HttpMethod, UriBuilder.Uri);

            if (this.PathParams.Any())
            {
                var path = HttpUtility.UrlDecode(UriBuilder.Path);
                foreach (var p in this.PathParams)
                {
                    path = path.Replace("{" + p.Key + "}", p.Value, StringComparison.OrdinalIgnoreCase);
                }
                UriBuilder.Path = HttpUtility.UrlPathEncode(path);
            }

            if (this.QueryStrings.Any())
            {
                UriBuilder.Query = string.Join("&", this.QueryStrings.Select(q => q.Key + "=" + HttpUtility.UrlEncode(q.Value)));
            }

            if (this.HttpMethod == HttpMethod.Post || this.HttpMethod.Method == "PATCH" ||
                this.HttpMethod == HttpMethod.Put)
            {
                if (this.MultiPartAttribute != null)
                {
                    var multipleContent = new MultipartContent(this.MultiPartAttribute.MultiPartType, Guid.NewGuid().ToString());

                    if (FormBodys.Any())
                    {
                        var content = new FormUrlEncodedContent(this.FormBodys);
                        multipleContent.Add(content);
                    }
                    if (JsonBody != null)
                    {
                        var content = new StringContent(JsonBody.ToString(), Utf8Encoding, "application/json");
                        multipleContent.Add(content);
                    }

                    if (RawContents.Any())
                    {
                        foreach (var c in RawContents)
                        {
                            multipleContent.Add(c);
                        }
                    }

                    //if (Files != null)
                    //{
                    //    foreach (var f in Files)
                    //    {
                    //        var content = new StreamContent(f.Value.OpenRead());
                    //        content.Headers.ContentDisposition = new ContentDispositionHeaderValue(this.MultiPartAttribute.MultiPartType);
                    //        content.Headers.ContentDisposition.FileName = f.Value.Name;
                    //        content.Headers.ContentDisposition.Name = f.Key;
                    //        content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(f.Value.Name));
                    //        multipleContent.Add(content);
                    //    }
                    //}
                    //if (StreamBodys != null)
                    //{
                    //    foreach (var s in StreamBodys)
                    //    {
                    //        var content = new StreamContent(s.Item2);
                    //        content.Headers.ContentType = new MediaTypeHeaderValue(s.Item1);
                    //        multipleContent.Add(content);
                    //    }
                    //}

                    httpMessage.Content = multipleContent;
                }
                else
                {
                    if (new[] {
                        FormBodys.Any(),
                        JsonBody != null,
                        RawContents.Any()
                    }.Count(i => i == true) > 1)
                    {
                        throw new NotSupportedException("Not support multiple kinds of http content in a message!");
                    }

                    if (FormBodys.Any())
                    {
                        httpMessage.Content = new FormUrlEncodedContent(this.FormBodys);
                        if (httpMessage.Content.Headers != null && httpMessage.Content.Headers.ContentType != null)
                        {
                            httpMessage.Content.Headers.ContentType.CharSet = Utf8Encoding.HeaderName;
                        }
                    }
                    else if (JsonBody != null)
                    {
                        httpMessage.Content = new StringContent(JsonBody.ToString(), Utf8Encoding, "application/json");
                        if (httpMessage.Content.Headers != null && httpMessage.Content.Headers.ContentType != null)
                        {
                            httpMessage.Content.Headers.ContentType.CharSet = Utf8Encoding.HeaderName;
                        }
                    }
                    if (RawContents.Any())
                    {
                        httpMessage.Content = RawContents.FirstOrDefault();
                    }
                    //else if (StreamBodys.Any())
                    //{
                    //    var stream = StreamBodys.FirstOrDefault();
                    //    httpMessage.Content = new StreamContent(stream.Item2);
                    //    httpMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(stream.Item1);
                    //}
                    //else if (Files.Any())
                    //{
                    //    var f = Files.FirstOrDefault();
                    //    var content = new StreamContent(f.Value.OpenRead());
                    //    content.Headers.ContentDisposition = new ContentDispositionHeaderValue(this.MultiPartAttribute.MultiPartType);
                    //    content.Headers.ContentDisposition.FileName = f.Value.Name;
                    //    content.Headers.ContentDisposition.Name = f.Key;
                    //    content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(f.Value.Name));
                    //    httpMessage.Content = content;
                    //}
                }
            }
            httpMessage.RequestUri = this.UriBuilder.Uri;


            foreach (var h in this.Headers.GroupBy(h => h.Key))
            {
                httpMessage.Headers.TryAddWithoutValidation(h.Key, h.Select(i => i.Value));
            }

            foreach (var c in this.Cookies)
            {
                httpMessage.Headers.GetCookies().Add(c);
            }


            return(httpMessage);
        }
示例#20
0
        /// <summary>
        /// Writes the response in one-step, and then closes the response stream
        /// </summary>
        /// <returns><c>true</c>, if written successfully, <c>false</c> otherwise.</returns>
        public bool WriteToContext()
        {
            bool syncWrite = true;

            if (_requestMethod != "HEAD")
            {
                if (JsonBody != null)
                {
                    if (!Chunked && !Headers.ContainsKey("Content-Type"))
                    {
                        var accept = _requestHeaders["Accept"];
                        if (accept != null)
                        {
                            if (accept.Contains("*/*") || accept.Contains("application/json"))
                            {
                                _responseWriter.AddHeader("Content-Type", "application/json");
                            }
                            else if (accept.Contains("text/plain"))
                            {
                                _responseWriter.AddHeader("Content-Type", "text/plain; charset=utf-8");
                            }
                            else
                            {
                                Reset();
                                _responseWriter.AddHeader("Content-Type", "application/json");
                                InternalStatus = StatusCode.NotAcceptable;
                            }
                        }
                    }

                    var json = default(byte[]);
                    try {
                        json = JsonBody.AsJson().ToArray();
                    } catch (Exception e) {
                        Log.To.Router.E(TAG, "Invalid body on response", e);
                        json = null;
                    }

                    if (!Chunked)
                    {
                        _responseWriter.ContentEncoding = Encoding.UTF8;
                        _responseWriter.ContentLength   = json.Length;
                    }

                    if (!WriteToStream(json))
                    {
                        return(false);
                    }
                }
                else if (BinaryBody != null)
                {
                    this["Content-Type"]            = BaseContentType;
                    _responseWriter.ContentEncoding = Encoding.UTF8;
                    var data = BinaryBody.ToArray();
                    if (!Chunked)
                    {
                        _responseWriter.ContentLength = data.LongLength;
                    }

                    if (!WriteToStream(data))
                    {
                        return(false);
                    }
                }
                else if (MultipartWriter != null)
                {
                    _responseWriter.ContentLength = MultipartWriter.Length;
                    MultipartWriter.WriteAsync(_responseWriter.OutputStream).ContinueWith(t =>
                    {
                        if (t.IsCompleted && t.Result)
                        {
                            TryClose();
                        }
                        else
                        {
                            Log.To.Router.I(TAG, "Multipart async write did not finish properly");
                        }
                    });
                    syncWrite = false;
                }
            }

            if (syncWrite)
            {
                TryClose();
            }

            return(true);
        }
示例#21
0
 IRequestBuilder IMessageBuilder <IRequestBuilder> .WithBody(object body)
 {
     RequestBody = new JsonBody(body);
     return(this);
 }
示例#22
0
        public void RenderWithoutBody_ShouldReturnNull()
        {
            var jBody = new JsonBody(null);

            jBody.Render().Should().BeNull();
        }
        /// <summary>
        /// Base handler for making the api request
        /// </summary>
        /// <param name="httpMethod"></param>
        /// <param name="requestToDownloadFile"></param>
        /// <returns></returns>
        private async Task <TestApiResponse> SendRequestAsync(HttpMethod httpMethod, string requestToDownloadFile = null)
        {
            var httpClientHandler = new HttpClientHandler
            {
                AllowAutoRedirect      = true,
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                CookieContainer        = new CookieContainer(),
                UseCookies             = true
            };

            if (_handleSslCertificateErrors)
            {
                httpClientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                {
                    if (_logSslCertificateErrors)
                    {
                        Runtime.Logger.Log($"Problem with the Certificate: {cert.Subject}");
                        Runtime.Logger.Log($"Sender: {sender}");
                        Runtime.Logger.Log($"cert: {cert}");
                        Runtime.Logger.Log($"chain: {chain}");
                        Runtime.Logger.Log($"sslPolicyErrors: {sslPolicyErrors}");
                    }
                    return(true);
                };
            }

            if (NtmlAuthentication)
            {
                httpClientHandler.UseDefaultCredentials = true;
            }

            var client = new HttpClient(httpClientHandler);

            if (HeaderAuthentication != null)
            {
                client.DefaultRequestHeaders.Authorization = HeaderAuthentication;
            }

            client.Timeout = TimeSpan.FromSeconds(SeAppConfig.DefaultApiResponseTimeoutWaitPeriodInSeconds);

            foreach (var kvp in Headers)
            {
                client.DefaultRequestHeaders.TryAddWithoutValidation(kvp.Key, kvp.Value);
            }

            foreach (Cookie cookie in Cookies)
            {
                httpClientHandler.CookieContainer.Add(cookie);
            }

            HttpResponseMessage httpResponseMessage = null;

            if (httpMethod == HttpMethod.Post)
            {
                if (JsonBody.IsEmpty() && Body.IsEmpty())
                {
                    var content = new FormUrlEncodedContent(PostParams.Select(kvp => new KeyValuePair <string, string>(kvp.Key, (string)kvp.Value)));
                    httpResponseMessage = await client.PostAsync(Uri.AbsoluteUri, content);
                }
                else if (JsonBody.HasValue())
                {
                    var request = new HttpRequestMessage(httpMethod, Uri);
                    request.Content     = new StringContent(JsonBody, Encoding.UTF8, "application/json");
                    httpResponseMessage = await client.SendAsync(request);
                }
                else if (Body.HasValue())
                {
                    var request = new HttpRequestMessage(httpMethod, Uri);
                    request.Content     = new StringContent(Body, Encoding.UTF8, "text/xml");
                    httpResponseMessage = await client.SendAsync(request);
                }
            }
            else if (httpMethod == HttpMethod.Put)
            {
                if (JsonBody.IsEmpty() && Body.IsEmpty())
                {
                    var content = new FormUrlEncodedContent(PostParams.Select(kvp => new KeyValuePair <string, string>(kvp.Key, (string)kvp.Value)));
                    httpResponseMessage = await client.PutAsync(Uri.AbsoluteUri, content);
                }
                else if (JsonBody.HasValue())
                {
                    var request = new HttpRequestMessage(httpMethod, Uri);
                    request.Content     = new StringContent(JsonBody, Encoding.UTF8, "application/json");
                    httpResponseMessage = await client.SendAsync(request);
                }
                else if (Body.HasValue())
                {
                    var request = new HttpRequestMessage(httpMethod, Uri);
                    request.Content     = new StringContent(Body, Encoding.UTF8, "text/xml");
                    httpResponseMessage = await client.SendAsync(request);
                }
            }
            else if (httpMethod == HttpMethod.Get)
            {
                Runtime.Logger.Log($"Requesting GET: {Uri.AbsoluteUri}");
                httpResponseMessage = requestToDownloadFile.IsEmpty() ? await client.GetAsync(Uri) : await client.GetAsync(Uri, HttpCompletionOption.ResponseHeadersRead);
            }
            else if (httpMethod == HttpMethod.Delete)
            {
                if (JsonBody.IsEmpty())
                {
                    Runtime.Logger.Log($"Requesting DELETE: {Uri.AbsoluteUri}");
                    httpResponseMessage = await client.DeleteAsync(Uri);
                }
                else
                {
                    var request = new HttpRequestMessage(httpMethod, Uri);
                    request.Content     = new StringContent(JsonBody, Encoding.UTF8, "application/json");
                    httpResponseMessage = await client.SendAsync(request);
                }
            }

            var schemeHostAndPortPart = Uri.GetLeftPart(UriPartial.Authority);
            var uri = new Uri(schemeHostAndPortPart);

            if (requestToDownloadFile.HasValue())
            {
                IoHelper.CreateDirectory(requestToDownloadFile);
                if (!File.Exists(requestToDownloadFile))
                {
                    using (Stream streamToReadFrom = await httpResponseMessage.Content.ReadAsStreamAsync())
                        using (Stream output = File.OpenWrite(requestToDownloadFile))
                        {
                            streamToReadFrom.CopyTo(output);
                        }
                }
                return(new TestApiResponse()
                {
                    ResponseCode = httpResponseMessage.StatusCode,
                    Cookies = httpClientHandler.CookieContainer.GetCookies(uri),
                    ResponseBody = null,
                    HttpResponseMessage = httpResponseMessage,
                });
            }

            var result = await httpResponseMessage.Content.ReadAsStringAsync();

            var response = new TestApiResponse()
            {
                ResponseCode        = httpResponseMessage.StatusCode,
                Cookies             = httpClientHandler.CookieContainer.GetCookies(uri),
                ResponseBody        = new TestApiBody(result),
                HttpResponseMessage = httpResponseMessage,
            };

            if (response.ResponseCode != HttpStatusCode.OK && response.ResponseCode != HttpStatusCode.Accepted)
            {
                Runtime.Logger.Log($"Resposne status: {response.ResponseCode}, ResponseMessage: {response.ResponseBody.ContentString}");
            }

            return(response);
        }
示例#24
0
        private void cbRESTQuery_SelectedValueChanged(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;

                string apiVersion = null;
                dgRequestHeaders.Rows.Clear();

                if (rdoV1.Checked)
                {
                    apiVersion = "v1.0/";
                }
                else if (rdoV2.Checked)
                {
                    apiVersion = "v2.0/";
                }
                else
                {
                    apiVersion = "beta/";
                }

                // lookup the selected value and populate the request information
                foreach (KeyValuePair <string, string> pair in dictionary)
                {
                    if (pair.Key == cbRESTQuery.SelectedItem.ToString())
                    {
                        tbRequestUrl.Text = Properties.Settings.Default.GraphEndpoint + apiVersion + pair.Value;

                        // check for examples where we need to create json for the POST body
                        if (pair.Key == "OutlookMail-SendNewMessage")
                        {
                            tbRequestBody.Text = JsonBody.CreateMessageJson();

                            // set headers and POST
                            cmbHttpMethod.Text = "POST";
                        }
                        else if (pair.Key == "OutlookMail-CreateDraftMessage")
                        {
                            tbRequestBody.Text = JsonBody.CreateDraftMessageJson();
                            cmbHttpMethod.Text = "POST";
                        }
                        else if (pair.Key == "OutlookCalendar-CreateEvent")
                        {
                            tbRequestBody.Text = JsonBody.CreateEventJson();
                            cmbHttpMethod.Text = "POST";
                        }
                        else if (pair.Key == "OutlookContacts-CreateContact")
                        {
                            tbRequestBody.Text = JsonBody.CreateContactJson();
                            cmbHttpMethod.Text = "POST";
                        }
                        else if (pair.Key == "OutlookNotifications-CreatePushSubscription")
                        {
                            Guid id = Guid.NewGuid();
                            notificationGuids.Add(id.ToString());
                            tbRequestBody.Text = JsonBody.CreateSubscriptionJson(id.ToString());
                            cmbHttpMethod.Text = "POST";
                            AddRequestHeader("Accept", "application/json");
                            AddRequestHeader("ContentType", "text/plain");
                        }
                        else if (pair.Key == "OutlookMail-CreateFolder")
                        {
                            tbRequestBody.Text = JsonBody.CreateMailFolder("MyTestFolder");
                            cmbHttpMethod.Text = "POST";
                        }
                        else
                        {
                            // use the same settings for all GET requests
                            AddRequestHeader("Accept", "application/json");
                            AddRequestHeader("x-AnchorMailbox", xAnchorMbx);
                            cmbHttpMethod.Text = "GET";
                            tbRequestBody.Text = "";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Log(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
                Properties.Settings.Default.NextLink = "";
            }
        }