Exemple #1
0
        /// <summary>
        ///     Send link address to direct thread
        /// </summary>
        /// <param name="text">Text to send</param>
        /// <param name="link">Link to send</param>
        /// <param name="threadIds">Thread ids</param>
        /// <param name="recipients">Recipients ids</param>
        private async Task <Result <ItemAckPayloadResponse> > SendDirectLink(string text, IEnumerable <string> link,
                                                                             string[] threadIds,
                                                                             long[] recipients)
        {
            ValidateLoggedIn();
            try
            {
                var instaUri      = UriCreator.GetSendDirectLinkUri();
                var clientContext = Guid.NewGuid().ToString();
                var data          = new Dictionary <string, string>
                {
                    { "link_text", text ?? string.Empty },
                    { "link_urls", JsonConvert.SerializeObject(link, Formatting.None) },
                    { "action", "send_item" },
                    { "client_context", clientContext },
                    { "_csrftoken", Session.CsrfToken },
                    { "_uuid", Device.Uuid.ToString() }
                };
                if (threadIds?.Length > 0)
                {
                    data.Add("thread_ids", JsonConvert.SerializeObject(threadIds, Formatting.None));
                }
                if (recipients?.Length > 0)
                {
                    var recipientString = string.Join(",", recipients);
                    data.Add("recipient_users", $"[[{recipientString}]]");
                }

                var response = await _httpClient.PostAsync(instaUri, new HttpFormUrlEncodedContent(data));

                var json = await response.Content.ReadAsStringAsync();

                _logger?.LogResponse(response);

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <ItemAckPayloadResponse> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <ItemAckResponse>(json);
                return(obj.IsOk()
                    ? Result <ItemAckPayloadResponse> .Success(obj.Payload, json, obj.Message)
                    : Result <ItemAckPayloadResponse> .Fail(json, obj.Message));
            }
            catch (Exception exception)
            {
                _logger?.LogException(exception);
                return(Result <ItemAckPayloadResponse> .Except(exception));
            }
        }
        public async Task <Result <ItemAckPayloadResponse> > SendReelReactAsync(long reelId, string mediaId, string threadId, string text)
        {
            ValidateLoggedIn();
            try
            {
                var uri           = UriCreator.GetDirectReelReactUri();
                var clientContext = Guid.NewGuid().ToString();
                var jsonObject    = new JObject
                {
                    { "action", "send_item" },
                    { "client_context", clientContext },
                    { "mutation_token", clientContext },
                    { "reel_id", reelId.ToString() },
                    { "media_id", mediaId },
                    { "thread_ids", $"[{threadId}]" },
                    { "text", text },
                    { "reaction_emoji", text },
                    { "entry", "reel" },
                    { "device_id", Device.DeviceId },
                    { "_csrftoken", Session.CsrfToken },
                    { "_uuid", Device.Uuid.ToString() },
                    { "_uid", Session.LoggedInUser.Pk.ToString() }
                };
                var signature = $"SIGNATURE.{jsonObject.ToString(Formatting.None)}";
                var data      = new Dictionary <string, string>
                {
                    { "signed_body", signature }
                };
                var response = await _httpClient.PostAsync(uri, new HttpFormUrlEncodedContent(data));

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <ItemAckPayloadResponse> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <ItemAckResponse>(json);
                return(obj.IsOk()
                    ? Result <ItemAckPayloadResponse> .Success(obj.Payload, json, obj.Message)
                    : Result <ItemAckPayloadResponse> .Fail(json, obj.Message));
            }
            catch (Exception exception)
            {
                DebugLogger.LogException(exception);
                return(Result <ItemAckPayloadResponse> .Except(exception));
            }
        }
        public async Task <Result <Dictionary <long, Reel> > > GetReels(ICollection <long> userIds)
        {
            ValidateLoggedIn();
            try
            {
                if (userIds == null || userIds.Count == 0)
                {
                    throw new ArgumentException("user ids is empty", nameof(userIds));
                }
                var uri  = UriCreator.GetReelsMediaUri();
                var data = new JObject
                {
                    { "supported_capabilities_new", ReelsCapabilities },
                    { "source", "reel_feed_timeline" },
                    { "_csrftoken", Session.CsrfToken },
                    { "_uid", Session.LoggedInUser.Pk.ToString() },
                    { "_uuid", Device.Uuid.ToString() },
                    { "user_ids", new JArray(userIds.Select(x => x.ToString()).ToArray()) }
                };
                var body = new Dictionary <string, string>
                {
                    { "signed_body", $"SIGNATURE.{data.ToString(Formatting.None)}" }
                };
                var response = await _httpClient.PostAsync(uri, new HttpFormUrlEncodedContent(body));

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);
                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <Dictionary <long, Reel> > .Fail(json, response.ReasonPhrase));
                }
                var payload = JsonConvert.DeserializeObject <JObject>(json);
                if (payload["status"]?.ToString() != "ok")
                {
                    return(Result <Dictionary <long, Reel> > .Fail(json));
                }
                var reels = payload["reels"].ToObject <Dictionary <long, Reel> >();
                return(Result <Dictionary <long, Reel> > .Success(reels, json));
            }
            catch (Exception e)
            {
                DebugLogger.LogException(e);
                return(Result <Dictionary <long, Reel> > .Except(e));
            }
        }
        public async Task <Result <GiphyMedia[]> > SearchAnimatedImageAsync(string query, AnimatedImageType type)
        {
            ValidateLoggedIn();
            try
            {
                string typeString;
                switch (type)
                {
                case AnimatedImageType.Sticker:
                    typeString = "giphy";
                    break;

                case AnimatedImageType.Gif:
                    typeString = "giphy_gifs";
                    break;

                default:
                    typeString = "giphy";
                    break;
                }
                var uri      = UriCreator.GetAnimatedImageSearchUri(query, typeString);
                var response = await _httpClient.GetAsync(uri);

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);
                if (!response.IsSuccessStatusCode)
                {
                    return(Result <GiphyMedia[]> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <JObject>(json);
                if (obj["status"]?.ToString() != "ok" || !obj.ContainsKey("results"))
                {
                    return(Result <GiphyMedia[]> .Fail(json));
                }
                var giphyResults = obj["results"]?[typeString]?.ToObject <GiphyMedia[]>();
                return(Result <GiphyMedia[]> .Success(giphyResults, json));
            }
            catch (Exception exception)
            {
                DebugLogger.LogException(exception);
                return(Result <GiphyMedia[]> .Except(exception));
            }
        }
Exemple #5
0
        /// <summary>
        ///     UnLike direct message in a thread
        /// </summary>
        /// <param name="threadId">Thread id</param>
        /// <param name="itemId">Item id (message id)</param>
        public async Task <Result <ItemAckResponse> > UnlikeItemAsync(string threadId, string itemId)
        {
            ValidateLoggedIn();
            try
            {
                var instaUri = UriCreator.GetLikeUnlikeDirectMessageUri();

                var data = new Dictionary <string, string>
                {
                    { "item_type", "reaction" },
                    { "reaction_type", "like" },
                    { "action", "send_item" },
                    { "_csrftoken", Session.CsrfToken },
                    { "_uuid", Device.Uuid.ToString() },
                    { "thread_ids", $"[{threadId}]" },
                    { "client_context", Guid.NewGuid().ToString() },
                    { "node_type", "item" },
                    { "reaction_status", "deleted" },
                    { "item_id", itemId }
                };
                var response = await _httpClient.PostAsync(instaUri, new HttpFormUrlEncodedContent(data));

                var json = await response.Content.ReadAsStringAsync();

                _logger?.LogResponse(response);

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <ItemAckResponse> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <ItemAckResponse>(json);
                return(obj.IsOk() ? Result <ItemAckResponse> .Success(obj, json, obj.Message) : Result <ItemAckResponse> .Fail(json, obj.Message));
            }
            catch (Exception exception)
            {
                _logger?.LogException(exception);
                return(Result <ItemAckResponse> .Except(exception));
            }
        }
        public async Task <Result <DirectThread[]> > SendAnimatedImageAsync(string mediaId, bool isSticker, string threadId)
        {
            ValidateLoggedIn();
            try
            {
                var uri           = UriCreator.GetSendAnimatedImageUri();
                var clientContext = Guid.NewGuid().ToString();
                var data          = new Dictionary <string, string>
                {
                    { "thread_ids", $"[{threadId}]" },
                    { "client_context", clientContext },
                    { "is_sticker", isSticker.ToString().ToLower() },
                    { "_csrftoken", Session.CsrfToken },
                    { "id", mediaId },
                    { "device_id", Device.DeviceId },
                    { "mutation_token", clientContext },
                    { "_uuid", Device.Uuid.ToString() },
                };
                var response = await _httpClient.PostAsync(uri, new HttpFormUrlEncodedContent(data));

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);

                if (!response.IsSuccessStatusCode)
                {
                    return(Result <DirectThread[]> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <ItemAddedResponse>(json);
                return(obj.IsOk()
                    ? Result <DirectThread[]> .Success(obj.Threads, json)
                    : Result <DirectThread[]> .Fail(json));
            }
            catch (Exception exception)
            {
                DebugLogger.LogException(exception);
                return(Result <DirectThread[]> .Except(exception));
            }
        }
Exemple #7
0
        /// <summary>
        ///     Mark direct message as seen
        /// </summary>
        /// <param name="threadId">Thread id</param>
        /// <param name="itemId">Message id (item id)</param>
        public async Task <Result <bool> > MarkItemSeenAsync(string threadId, string itemId)
        {
            ValidateLoggedIn();
            try
            {
                var instaUri = UriCreator.GetDirectThreadSeenUri(threadId, itemId);

                var data = new Dictionary <string, string>
                {
                    { "thread_id", threadId },
                    { "action", "mark_seen" },
                    { "_csrftoken", Session.CsrfToken },
                    { "_uuid", Device.Uuid.ToString() },
                    { "item_id", itemId },
                    { "use_unified_inbox", "true" },
                };
                var response = await _httpClient.PostAsync(instaUri, new HttpFormUrlEncodedContent(data));

                var json = await response.Content.ReadAsStringAsync();

                _logger?.LogResponse(response);

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <bool> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <DefaultResponse>(json);
                return(obj.IsOk()
                    ? Result <bool> .Success(true, json, obj.Message)
                    : Result <bool> .Fail(json, obj.Message));
            }
            catch (Exception exception)
            {
                _logger?.LogException(exception);
                return(Result <bool> .Except(exception));
            }
        }
Exemple #8
0
        private async Task <Result <InboxContainer> > GetDirectInbox(string maxId = null)
        {
            try
            {
                var directInboxUri = UriCreator.GetDirectInboxUri(maxId);
                var response       = await _httpClient.GetAsync(directInboxUri);

                var json = await response.Content.ReadAsStringAsync();

                _logger?.LogResponse(response);

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <InboxContainer> .Fail(json, response.ReasonPhrase));
                }
                var inbox = JsonConvert.DeserializeObject <InboxContainer>(json);
                return(Result <InboxContainer> .Success(inbox));
            }
            catch (Exception exception)
            {
                _logger?.LogException(exception);
                return(Result <InboxContainer> .Except(exception));
            }
        }
        public async Task <Result <UserPresenceResponse> > GetPresence()
        {
            ValidateLoggedIn();
            try
            {
                var instaUri = UriCreator.GetDirectUserPresenceUri();
                var response = await _httpClient.GetAsync(instaUri);

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);
                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    return(Result <UserPresenceResponse> .Fail(json, response.ReasonPhrase));
                }
                var obj = JsonConvert.DeserializeObject <UserPresenceResponse>(json);
                return(obj.IsOk() ? Result <UserPresenceResponse> .Success(obj, json) : Result <UserPresenceResponse> .Fail(json));
            }
            catch (Exception exception)
            {
                DebugLogger.LogException(exception);
                return(Result <UserPresenceResponse> .Except(exception));
            }
        }
        private async Task <Result <bool> > ConfigureVideo(Action <UploaderProgress> progress, UploaderProgress upProgress, string uploadId, bool isDirectVideo, bool isDisappearingVideo, string caption,
                                                           VisualMediaViewMode viewMode, InstaStoryType storyType, string recipients, string threadId, Uri uri, StoryUploadOptions uploadOptions = null)
        {
            try
            {
                upProgress.UploadState = InstaUploadState.Configuring;
                progress?.Invoke(upProgress);
                var instaUri      = UriCreator.GetDirectConfigVideoUri();
                var retryContext  = GetRetryContext();
                var clientContext = Guid.NewGuid().ToString();

                if (isDirectVideo)
                {
                    var data = new Dictionary <string, string>
                    {
                        { "action", "send_item" },
                        { "client_context", clientContext },
                        { "_csrftoken", Session.CsrfToken },
                        { "video_result", "" },
                        { "_uuid", Device.Uuid.ToString() },
                        { "upload_id", uploadId }
                    };
                    if (!string.IsNullOrEmpty(recipients))
                    {
                        data.Add("recipient_users", $"[[{recipients}]]");
                    }
                    else
                    {
                        data.Add("thread_ids", $"[{threadId}]");
                    }

                    instaUri = UriCreator.GetDirectConfigVideoUri();
                    var request = new HttpRequestMessage(HttpMethod.Post, instaUri);
                    request.Content = new HttpFormUrlEncodedContent(data);
                    request.Headers.Add("retry_context", retryContext);
                    var response = await _httpClient.SendRequestAsync(request);

                    var json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    if (response.StatusCode != HttpStatusCode.Ok)
                    {
                        upProgress.UploadState = InstaUploadState.Error;
                        progress?.Invoke(upProgress);
                        return(Result <bool> .Fail(json, response.ReasonPhrase));
                    }
                    var obj = JsonConvert.DeserializeObject <DefaultResponse>(json);

                    if (obj.Status.ToLower() == "ok")
                    {
                        upProgress.UploadState = InstaUploadState.Configured;
                        progress?.Invoke(upProgress);
                    }
                    else
                    {
                        upProgress.UploadState = InstaUploadState.Completed;
                        progress?.Invoke(upProgress);
                    }

                    return(obj.IsOk()
                        ? Result <bool> .Success(true, json, obj.Message)
                        : Result <bool> .Fail(json, obj.Message));
                }
                else
                {
                    var rnd  = new Random();
                    var data = new JObject
                    {
                        { "filter_type", "0" },
                        { "timezone_offset", "16200" },
                        { "_csrftoken", Session.CsrfToken },
                        { "client_shared_at", (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - rnd.Next(25, 55)).ToString() },
                        { "story_media_creation_date", (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - rnd.Next(50, 70)).ToString() },
                        { "media_folder", "Camera" },
                        { "source_type", "4" },
                        { "video_result", "" },
                        { "_uid", Session.LoggedInUser.Pk.ToString() },
                        { "_uuid", Device.Uuid.ToString() },
                        { "caption", caption ?? string.Empty },
                        { "date_time_original", DateTimeOffset.Now.ToString("yyyy-dd-MMTh:mm:ss-0fffZ") },
                        { "capture_type", "normal" },
                        { "mas_opt_in", "NOT_PROMPTED" },
                        { "upload_id", uploadId },
                        { "client_timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
                        {
                            "device", new JObject {
                                { "manufacturer", Device.HardwareManufacturer },
                                { "model", Device.HardwareModel },
                                { "android_release", Device.AndroidVersion.VersionNumber },
                                { "android_version", Device.AndroidVersion.APILevel }
                            }
                        },
                        { "length", 0 },
                        {
                            "extra", new JObject
                            {
                                { "source_width", 0 },
                                { "source_height", 0 }
                            }
                        },
                        { "audio_muted", false },
                        { "poster_frame_index", 0 },
                    };
                    if (isDisappearingVideo)
                    {
                        data.Add("view_mode", viewMode.ToString().ToLower());
                        data.Add("configure_mode", "2");
                        data.Add("recipient_users", "[]");
                        data.Add("thread_ids", $"[{threadId}]");
                    }
                    else
                    {
                        switch (storyType)
                        {
                        case InstaStoryType.SelfStory:
                        default:
                            data.Add("configure_mode", "1");
                            break;

                        case InstaStoryType.Direct:
                            data.Add("configure_mode", "2");
                            data.Add("view_mode", "replayable");
                            data.Add("recipient_users", "[]");
                            data.Add("thread_ids", $"[{threadId}]");
                            break;

                        case InstaStoryType.Both:
                            data.Add("configure_mode", "3");
                            data.Add("view_mode", "replayable");
                            data.Add("recipient_users", "[]");
                            data.Add("thread_ids", $"[{threadId}]");
                            break;
                        }

                        if (uri != null)
                        {
                            var webUri = new JArray
                            {
                                new JObject
                                {
                                    { "webUri", uri.ToString() }
                                }
                            };
                            var storyCta = new JArray
                            {
                                new JObject
                                {
                                    { "links", webUri }
                                }
                            };
                            data.Add("story_cta", storyCta.ToString(Formatting.None));
                        }

                        if (uploadOptions != null)
                        {
                            if (uploadOptions.Hashtags?.Count > 0)
                            {
                                var hashtagArr = new JArray();
                                foreach (var item in uploadOptions.Hashtags)
                                {
                                    hashtagArr.Add(item.ToJson());
                                }

                                data.Add("story_hashtags", hashtagArr.ToString(Formatting.None));
                            }

                            if (uploadOptions.Locations?.Count > 0)
                            {
                                var locationArr = new JArray();
                                foreach (var item in uploadOptions.Locations)
                                {
                                    locationArr.Add(item.ToJson());
                                }

                                data.Add("story_locations", locationArr.ToString(Formatting.None));
                            }
                            if (uploadOptions.Slider != null)
                            {
                                var sliderArr = new JArray
                                {
                                    uploadOptions.Slider.ToJson()
                                };

                                data.Add("story_sliders", sliderArr.ToString(Formatting.None));
                                if (uploadOptions.Slider.IsSticker)
                                {
                                    data.Add("story_sticker_ids", $"emoji_slider_{uploadOptions.Slider.Emoji}");
                                }
                            }
                            else
                            {
                                if (uploadOptions.Polls?.Count > 0)
                                {
                                    var pollArr = new JArray();
                                    foreach (var item in uploadOptions.Polls)
                                    {
                                        pollArr.Add(item.ToJson());
                                    }

                                    data.Add("story_polls", pollArr.ToString(Formatting.None));
                                }
                                if (uploadOptions.Questions?.Count > 0)
                                {
                                    var questionArr = new JArray();
                                    foreach (var item in uploadOptions.Questions)
                                    {
                                        questionArr.Add(item.ToJson());
                                    }

                                    data.Add("story_questions", questionArr.ToString(Formatting.None));
                                }
                            }
                            if (uploadOptions.Countdown != null)
                            {
                                var countdownArr = new JArray
                                {
                                    uploadOptions.Countdown.ToJson()
                                };

                                data.Add("story_countdowns", countdownArr.ToString(Formatting.None));
                                data.Add("story_sticker_ids", "countdown_sticker_time");
                            }
                        }
                    }
                    instaUri = UriCreator.GetVideoStoryConfigureUri(true);
                    var request = GetSignedRequest(instaUri, data);

                    request.Headers.Add("retry_context", retryContext);
                    var response = await _httpClient.SendRequestAsync(request);

                    var json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    if (response.IsSuccessStatusCode)
                    {
                        var mediaResponse = JsonConvert.DeserializeObject <DefaultResponse>(json);

                        if (mediaResponse.IsOk())
                        {
                            upProgress.UploadState = InstaUploadState.Configured;
                            progress?.Invoke(upProgress);
                        }
                        else
                        {
                            upProgress.UploadState = InstaUploadState.Completed;
                            progress?.Invoke(upProgress);
                        }
                        return(mediaResponse.IsOk() ? Result <bool> .Success(true) : Result <bool> .Fail(json, mediaResponse.Message));
                    }
                    upProgress.UploadState = InstaUploadState.Error;
                    progress?.Invoke(upProgress);
                    return(Result <bool> .Fail(json, response.ReasonPhrase));
                }
            }
            catch (Exception exception)
            {
                upProgress.UploadState = InstaUploadState.Error;
                progress?.Invoke(upProgress);
                DebugLogger.LogException(exception);
                return(Result <bool> .Except(exception));
            }
        }
        public async Task <Result <ItemAckPayloadResponse> > SendDirectPhotoAsync(InstaImage image, string threadId,
                                                                                  long uploadId,
                                                                                  Action <UploaderProgress> progress = null)
        {
            var upProgress = new UploaderProgress
            {
                Caption     = string.Empty,
                UploadState = InstaUploadState.Preparing
            };

            try
            {
                var entityName = "direct_" + uploadId;
                var uri        = UriCreator.GetDirectSendPhotoUri(entityName);
                upProgress.UploadId = uploadId.ToString();
                progress?.Invoke(upProgress);
                var ruploadParams = new JObject(
                    new JProperty("media_type", 1),
                    new JProperty("upload_id", uploadId.ToString()),
                    new JProperty("upload_media_height", image.Height),
                    new JProperty("upload_media_width", image.Width));
                var requestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
                requestMessage.Headers.Add("X-Entity-Name", entityName);
                requestMessage.Headers.Add("X-Instagram-Rupload-Params", ruploadParams.ToString(Formatting.None));
                requestMessage.Headers.Add("Offset", "0");
                var uploadBuffer = image.UploadBuffer;
                var content      = new HttpBufferContent(uploadBuffer);
                content.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("image/jpeg");
                requestMessage.Headers.Add("X-Entity-Length", uploadBuffer.Length.ToString());
                requestMessage.Content = content;
                upProgress.UploadState = InstaUploadState.Uploading;
                progress?.Invoke(upProgress);
                var response = await _httpClient.SendRequestAsync(requestMessage);

                var json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);

                var ruploadResp = JsonConvert.DeserializeObject <RuploadResponse>(json);
                if (response.StatusCode != HttpStatusCode.Ok || !ruploadResp.IsOk())
                {
                    upProgress.UploadState = InstaUploadState.Error;
                    progress?.Invoke(upProgress);
                    return(Result <ItemAckPayloadResponse> .Fail(json));
                }

                var uploadIdResp = ruploadResp.UploadId;
                upProgress.UploadState = InstaUploadState.Uploaded;
                progress?.Invoke(upProgress);
                var configUri = UriCreator.GetDirectConfigPhotoUri();
                var config    = new Dictionary <string, string>(7)
                {
                    ["action"] = "send_item",
                    ["allow_full_aspect_ratio"] = "1",
                    ["content_type"]            = "photo",
                    ["mutation_token"]          = Guid.NewGuid().ToString(),
                    ["sampled"]   = "1",
                    ["thread_id"] = threadId,
                    ["upload_id"] = uploadIdResp
                };
                response = await _httpClient.PostAsync(configUri, new HttpFormUrlEncodedContent(config));

                json = await response.Content.ReadAsStringAsync();

                DebugLogger.LogResponse(response);
                var obj = JsonConvert.DeserializeObject <ItemAckResponse>(json);
                if (response.StatusCode != HttpStatusCode.Ok || !obj.IsOk())
                {
                    upProgress.UploadState = InstaUploadState.Error;
                    progress?.Invoke(upProgress);
                    return(Result <ItemAckPayloadResponse> .Fail(json, obj.Message));
                }

                upProgress.UploadState = InstaUploadState.Completed;
                progress?.Invoke(upProgress);
                return(Result <ItemAckPayloadResponse> .Success(obj.Payload, json, obj.Message));
            }
            catch (Exception exception)
            {
                upProgress.UploadState = InstaUploadState.Error;
                progress?.Invoke(upProgress);
                DebugLogger.LogException(exception);
                return(Result <ItemAckPayloadResponse> .Except(exception));
            }
        }
        /// <summary>
        ///     Send video story, direct video, disappearing video
        /// </summary>
        /// <param name="isDirectVideo">Direct video</param>
        /// <param name="isDisappearingVideo">Disappearing video</param>
        private async Task <Result <bool> > SendVideoAsync(Action <UploaderProgress> progress, bool isDirectVideo, bool isDisappearingVideo, string caption,
                                                           VisualMediaViewMode viewMode, InstaStoryType storyType, string recipients, string threadId, InstaVideoUpload video, Uri uri = null, StoryUploadOptions uploadOptions = null)
        {
            var upProgress = new UploaderProgress
            {
                Caption     = caption ?? string.Empty,
                UploadState = InstaUploadState.Preparing
            };

            try
            {
                var uploadId        = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
                var videoHashCode   = video.Video.Url?.GetHashCode() ?? $"C:\\{GenerateRandomString(13)}.mp4".GetHashCode();
                var waterfallId     = Guid.NewGuid().ToString();
                var videoEntityName = $"{uploadId}_0_{videoHashCode}";
                var videoUri        = UriCreator.GetStoryUploadVideoUri(uploadId, videoHashCode);
                var retryContext    = GetRetryContext();
                HttpRequestMessage  request;
                HttpResponseMessage response;
                string videoUploadParams = null;
                string json = null;
                upProgress.UploadId = uploadId;
                progress?.Invoke(upProgress);
                var videoUploadParamsObj = new JObject();
                if (isDirectVideo)
                {
                    videoUploadParamsObj = new JObject
                    {
                        { "upload_media_height", "0" },
                        { "direct_v2", "1" },
                        { "upload_media_width", "0" },
                        { "upload_media_duration_ms", "0" },
                        { "upload_id", uploadId },
                        { "retry_context", retryContext },
                        { "media_type", "2" }
                    };

                    videoUploadParams = JsonConvert.SerializeObject(videoUploadParamsObj);
                    request           = new HttpRequestMessage(HttpMethod.Get, videoUri);
                    request.Headers.Add("X_FB_VIDEO_WATERFALL_ID", waterfallId);
                    request.Headers.Add("X-Instagram-Rupload-Params", videoUploadParams);
                    response = await _httpClient.SendRequestAsync(request);

                    json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    if (response.StatusCode != HttpStatusCode.Ok)
                    {
                        upProgress.UploadState = InstaUploadState.Error;
                        progress?.Invoke(upProgress);
                        return(Result <bool> .Fail(json, response.ReasonPhrase));
                    }
                }
                else
                {
                    videoUploadParamsObj = new JObject
                    {
                        { "_csrftoken", Session.CsrfToken },
                        { "_uid", Session.LoggedInUser.Pk },
                        { "_uuid", Device.Uuid.ToString() },
                        {
                            "media_info", new JObject
                            {
                                { "capture_mode", "normal" },
                                { "media_type", 2 },
                                { "caption", caption ?? string.Empty },
                                { "mentions", new JArray() },
                                { "hashtags", new JArray() },
                                { "locations", new JArray() },
                                { "stickers", new JArray() },
                            }
                        }
                    };
                    request  = GetSignedRequest(UriCreator.GetStoryMediaInfoUploadUri(), videoUploadParamsObj);
                    response = await _httpClient.SendRequestAsync(request);

                    json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    videoUploadParamsObj = new JObject
                    {
                        { "upload_media_height", "0" },
                        { "upload_media_width", "0" },
                        { "upload_media_duration_ms", "0" },
                        { "upload_id", uploadId },
                        { "retry_context", "{\"num_step_auto_retry\":0,\"num_reupload\":0,\"num_step_manual_retry\":0}" },
                        { "media_type", "2" }
                    };
                    if (isDisappearingVideo)
                    {
                        videoUploadParamsObj.Add("for_direct_story", "1");
                    }
                    else
                    {
                        switch (storyType)
                        {
                        case InstaStoryType.SelfStory:
                        default:
                            videoUploadParamsObj.Add("for_album", "1");
                            break;

                        case InstaStoryType.Direct:
                            videoUploadParamsObj.Add("for_direct_story", "1");
                            break;

                        case InstaStoryType.Both:
                            videoUploadParamsObj.Add("for_album", "1");
                            videoUploadParamsObj.Add("for_direct_story", "1");
                            break;
                        }
                    }
                    videoUploadParams = JsonConvert.SerializeObject(videoUploadParamsObj);
                    request           = new HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, videoUri);
                    request.Headers.Add("X_FB_VIDEO_WATERFALL_ID", waterfallId);
                    request.Headers.Add("X-Instagram-Rupload-Params", videoUploadParams);
                    response = await _httpClient.SendRequestAsync(request);

                    json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    if (response.StatusCode != HttpStatusCode.Ok)
                    {
                        upProgress.UploadState = InstaUploadState.Error;
                        progress?.Invoke(upProgress);
                        return(Result <bool> .Fail(json, response.ReasonPhrase));
                    }
                }

                // video part
                IBuffer videoUploadBuffer;
                if (video.Video.UploadBuffer == null)
                {
                    if (video.Video.Url == null)
                    {
                        throw new NullReferenceException("No upload buffer or file path are provided for video upload.");
                    }
                    var videoFile = await StorageFile.GetFileFromPathAsync(video.Video.Url.AbsolutePath);

                    videoUploadBuffer = await FileIO.ReadBufferAsync(videoFile);
                }
                else
                {
                    videoUploadBuffer = video.Video.UploadBuffer;
                }

                var videoContent = new HttpBufferContent(videoUploadBuffer);

                request = new HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, videoUri)
                {
                    Content = videoContent
                };
                upProgress.UploadState = InstaUploadState.Uploading;
                progress?.Invoke(upProgress);
                var vidExt = Path.GetExtension(video.Video.Url?.AbsolutePath ?? $"C:\\{GenerateRandomString(13)}.mp4")
                             .Replace(".", "").ToLower();
                if (vidExt == "mov")
                {
                    request.Headers.Add("X-Entity-Type", "video/quicktime");
                }
                else
                {
                    request.Headers.Add("X-Entity-Type", "video/mp4");
                }

                request.Headers.Add("Offset", "0");
                request.Headers.Add("X-Instagram-Rupload-Params", videoUploadParams);
                request.Headers.Add("X-Entity-Name", videoEntityName);
                request.Headers.Add("X-Entity-Length", videoUploadBuffer.Length.ToString());
                request.Headers.Add("X_FB_VIDEO_WATERFALL_ID", waterfallId);
                response = await _httpClient.SendRequestAsync(request);

                json = await response.Content.ReadAsStringAsync();

                if (response.StatusCode != HttpStatusCode.Ok)
                {
                    upProgress.UploadState = InstaUploadState.Error;
                    progress?.Invoke(upProgress);
                    return(Result <bool> .Fail(json, response.ReasonPhrase));
                }
                upProgress.UploadState = InstaUploadState.Uploaded;
                progress?.Invoke(upProgress);
                //upProgress = progressContent?.UploaderProgress;
                if (!isDirectVideo)
                {
                    upProgress.UploadState = InstaUploadState.UploadingThumbnail;
                    progress?.Invoke(upProgress);
                    var photoHashCode        = video.VideoThumbnail.Url?.GetHashCode() ?? $"C:\\{GenerateRandomString(13)}.jpg".GetHashCode();
                    var photoEntityName      = $"{uploadId}_0_{photoHashCode}";
                    var photoUri             = UriCreator.GetStoryUploadPhotoUri(uploadId, photoHashCode);
                    var photoUploadParamsObj = new JObject
                    {
                        { "retry_context", retryContext },
                        { "media_type", "2" },
                        { "upload_id", uploadId },
                        { "image_compression", "{\"lib_name\":\"moz\",\"lib_version\":\"3.1.m\",\"quality\":\"95\"}" },
                    };

                    var     photoUploadParams = JsonConvert.SerializeObject(photoUploadParamsObj);
                    IBuffer thumbnailUploadBuffer;
                    if (video.VideoThumbnail.UploadBuffer == null)
                    {
                        if (video.VideoThumbnail.Url == null)
                        {
                            throw new NullReferenceException("No upload buffer or file path are provided for video thumbnail upload.");
                        }
                        var videoFile = await StorageFile.GetFileFromPathAsync(video.VideoThumbnail.Url.AbsolutePath);

                        thumbnailUploadBuffer = await FileIO.ReadBufferAsync(videoFile);
                    }
                    else
                    {
                        thumbnailUploadBuffer = video.VideoThumbnail.UploadBuffer;
                    }
                    var imageContent = new HttpBufferContent(thumbnailUploadBuffer);
                    imageContent.Headers.Add("Content-Transfer-Encoding", "binary");
                    imageContent.Headers.Add("Content-Type", "application/octet-stream");
                    request         = new HttpRequestMessage(HttpMethod.Post, photoUri);
                    request.Content = imageContent;
                    request.Headers.Add("X-Entity-Type", "image/jpeg");
                    request.Headers.Add("Offset", "0");
                    request.Headers.Add("X-Instagram-Rupload-Params", photoUploadParams);
                    request.Headers.Add("X-Entity-Name", photoEntityName);
                    request.Headers.Add("X-Entity-Length", thumbnailUploadBuffer.Length.ToString());
                    request.Headers.Add("X_FB_PHOTO_WATERFALL_ID", waterfallId);
                    response = await _httpClient.SendRequestAsync(request);

                    json = await response.Content.ReadAsStringAsync();

                    DebugLogger.LogResponse(response);

                    upProgress.UploadState = InstaUploadState.ThumbnailUploaded;
                    progress?.Invoke(upProgress);
                }
                return(await ConfigureVideo(progress, upProgress, uploadId, isDirectVideo, isDisappearingVideo, caption, viewMode, storyType, recipients, threadId, uri, uploadOptions));
            }
            catch (Exception exception)
            {
                upProgress.UploadState = InstaUploadState.Error;
                progress?.Invoke(upProgress);
                DebugLogger.LogException(exception);
                return(Result <bool> .Except(exception));
            }
        }