From b360435d387a15288674f264801c54f59eab9218 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sat, 6 May 2017 02:34:43 +0200 Subject: [PATCH 01/17] Added basic Instagram Stories support Added Instagram Stories from user trays (The stories you see on home page) Added Instagram Stories by user id --- InstaSharper.Tests/Endpoints/StoryTest.cs | 63 +++++++++ InstaSharper.Tests/InstaSharper.Tests.csproj | 2 +- InstaSharper/API/IInstaApi.cs | 22 ++++ InstaSharper/API/InstaApi.cs | 64 ++++++++++ InstaSharper/API/InstaApiConstants.cs | 2 + InstaSharper/Classes/Models/InstaStory.cs | 11 +- InstaSharper/Classes/Models/InstaStoryItem.cs | 83 ++++++++++++ InstaSharper/Classes/Models/InstaStoryTray.cs | 19 +++ InstaSharper/Classes/Models/MediaVideo.cs | 23 ++++ .../InstaStoryItemResponse.cs | 120 ++++++++++++++++++ .../ResponseWrappers/InstaStoryResponse.cs | 20 ++- .../InstaStoryTrayResponse.cs | 25 ++++ .../InstaVideoCandidatesResponse.cs | 11 ++ InstaSharper/Converters/ConvertersFabric.cs | 15 +++ .../Converters/InstaStoryConverter.cs | 14 +- .../Converters/InstaStoryItemConverter.cs | 68 ++++++++++ .../Converters/InstaStoryTrayConverter.cs | 28 ++++ InstaSharper/Helpers/UriCreator.cs | 15 +++ 18 files changed, 598 insertions(+), 7 deletions(-) create mode 100644 InstaSharper.Tests/Endpoints/StoryTest.cs create mode 100644 InstaSharper/Classes/Models/InstaStoryItem.cs create mode 100644 InstaSharper/Classes/Models/InstaStoryTray.cs create mode 100644 InstaSharper/Classes/Models/MediaVideo.cs create mode 100644 InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs create mode 100644 InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs create mode 100644 InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs create mode 100644 InstaSharper/Converters/InstaStoryItemConverter.cs create mode 100644 InstaSharper/Converters/InstaStoryTrayConverter.cs diff --git a/InstaSharper.Tests/Endpoints/StoryTest.cs b/InstaSharper.Tests/Endpoints/StoryTest.cs new file mode 100644 index 00000000..9322e4a2 --- /dev/null +++ b/InstaSharper.Tests/Endpoints/StoryTest.cs @@ -0,0 +1,63 @@ +using System; +using InstaSharper.Classes; +using InstaSharper.Tests.Utils; +using Xunit; +using Xunit.Abstractions; + + +namespace InstaSharper.Tests.Endpoints +{ + [Collection("Endpoints")] + class StoryTest + { + private readonly ITestOutputHelper _output; + private readonly string _password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); + private readonly string _username = "thisidlin"; + + public StoryTest(ITestOutputHelper output) + { + _output = output; + } + + [RunnableInDebugOnlyFact] + private async void GetStoryTray() + { + //arrange + var apiInstance = + TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = _username, + Password = _password + }); + //act + var loginSucceed = TestHelpers.Login(apiInstance, _output); + Assert.True(loginSucceed); + var result = await apiInstance.GetStoryTrayAsync(); + var stories = result.Value; + //assert + Assert.True(result.Succeeded); + Assert.NotNull(stories); + } + + [RunnableInDebugOnlyTheory] + [InlineData(1129166614)] + private async void GetUserStory(long userId) + { + //arrange + var apiInstance = + TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = _username, + Password = _password + }); + //act + var loginSucceed = TestHelpers.Login(apiInstance, _output); + Assert.True(loginSucceed); + var result = await apiInstance.GetUserStoryAsync(userId); + var stories = result.Value; + //assert + Assert.True(result.Succeeded); + Assert.NotNull(stories); + } + } +} diff --git a/InstaSharper.Tests/InstaSharper.Tests.csproj b/InstaSharper.Tests/InstaSharper.Tests.csproj index 00906169..8b412454 100644 --- a/InstaSharper.Tests/InstaSharper.Tests.csproj +++ b/InstaSharper.Tests/InstaSharper.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index c21e06bb..f968ec26 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -243,6 +243,17 @@ public interface IInstaApi /// IResult ConfigurePhoto(MediaImage image, string uploadId, string caption); + /// + /// Get user's Story Tray + /// + IResult GetStoryTray(); + + /// + /// Get the story by userId + /// + /// User Id + IResult GetUserStory(long userId); + #endregion #region Async Members @@ -478,6 +489,17 @@ public interface IInstaApi /// Task> ConfigurePhotoAsync(MediaImage image, string uploadId, string caption); + /// + /// Get user's Story Tray + /// + Task> GetStoryTrayAsync(); + + /// + /// Get the story by userId + /// + /// User Id + Task> GetUserStoryAsync(long userId); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index 4348acfa..26841d39 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -194,6 +194,16 @@ public IResult ConfigurePhoto(MediaImage image, string uploadId, str return ConfigurePhotoAsync(image, uploadId, caption).Result; } + public IResult GetStoryTray() + { + return GetStoryTrayAsync().Result; + } + + public IResult GetUserStory(long userId) + { + return GetUserStoryAsync(userId).Result; + } + #endregion #region async part @@ -1057,6 +1067,60 @@ public async Task> ConfigurePhotoAsync(MediaImage image, str } } + + public async Task> GetStoryTrayAsync() + { + ValidateUser(); + ValidateLoggedIn(); + + try + { + var storyTrayUri = UriCreator.GetStoryTray(); + var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, storyTrayUri, _deviceInfo); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaStoryTray)null); + var instaStoryTray = new InstaStoryTray(); + var instaStoryTrayResponse = JsonConvert.DeserializeObject(json); + + instaStoryTray = ConvertersFabric.GetStoryTrayConverter(instaStoryTrayResponse).Convert(); + + return Result.Success(instaStoryTray); + + } + catch (Exception exception) + { + return Result.Fail(exception.Message, (InstaStoryTray)null); + } + } + + public async Task> GetUserStoryAsync(long userId) + { + ValidateUser(); + ValidateLoggedIn(); + + try + { + var userStoryUri = UriCreator.GetUserStoryUri(userId); + var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, userStoryUri, _deviceInfo); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaStory)null); + var userStory = new InstaStory(); + var userStoryResponse = JsonConvert.DeserializeObject(json); + + userStory = ConvertersFabric.GetStoryConverter(userStoryResponse).Convert(); + + return Result.Success(userStory); + + } + catch (Exception exception) + { + return Result.Fail(exception.Message, (InstaStory)null); + } + } + #endregion #region private part diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index 835714b0..cbe34a9c 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -46,6 +46,8 @@ internal static class InstaApiConstants public const string DELETE_COMMENT = API_SUFFIX + "/v1/media/{0}/comment/{1}/delete/"; public const string UPLOAD_PHOTO = API_SUFFIX + "/v1/upload/photo/"; public const string MEDIA_CONFIGURE = API_SUFFIX + "/v1/media/configure/"; + public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; + public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; public const string HEADER_USER_AGENT = "User-Agent"; diff --git a/InstaSharper/Classes/Models/InstaStory.cs b/InstaSharper/Classes/Models/InstaStory.cs index 73476248..edfe1a31 100644 --- a/InstaSharper/Classes/Models/InstaStory.cs +++ b/InstaSharper/Classes/Models/InstaStory.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace InstaSharper.Classes.Models { @@ -12,7 +13,7 @@ public class InstaStory public string SourceToken { get; set; } - public bool Seen { get; set; } + public double Seen { get; set; } public string LatestReelMedia { get; set; } @@ -20,6 +21,14 @@ public class InstaStory public int RankedPosition { get; set; } + public bool Muted { get; set; } + public int SeenRankedPosition { get; set; } + + public List Items { get; set; } = new List(); + + public int PrefetchCount { get; set; } + + public string SocialContext { get; set; } } } \ No newline at end of file diff --git a/InstaSharper/Classes/Models/InstaStoryItem.cs b/InstaSharper/Classes/Models/InstaStoryItem.cs new file mode 100644 index 00000000..c98f7624 --- /dev/null +++ b/InstaSharper/Classes/Models/InstaStoryItem.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.Models +{ + public class InstaStoryItem + { + public DateTime TakenAt { get; set; } + + public long Pk { get; set; } + + public string Id { get; set; } + + public InstaMediaType MediaType { get; set; } + + public string Code { get; set; } + + public string ClientCacheKey { get; set; } + + public int FilterType { get; set; } + + public List Images { get; set; } = new List(); + + public int OriginalWidth { get; set; } + + public int OriginalHeight { get; set; } + + public double CaptionPosition { get; set; } + + public InstaUser User { get; set; } + + public string TrackingToken { get; set; } + + public int LikeCount { get; set; } + + public InstaUserList Likers { get; set; } = new InstaUserList(); + + public bool HasLiked { get; set; } + + public bool HasMoreComments { get; set; } + + public int MaxNumVisiblePreviewComments { get; set; } + + //public InstaComment PreviewComments { get; set; } --- --- //I'll check what is. + + public int CommentCount { get; set; } + + public bool CommentsDisabled { get; set; } + + public InstaCaption Caption { get; set; } + + public List UserTags { get; set; } = new List(); + + public InstaCarousel CarouselMedia { get; set; } = new InstaCarousel(); + + public bool CaptionIsEdited { get; set; } //Visible only if the story is an image. + + public bool PhotoOfYou { get; set; } + + #region Video + + public List VideoVersions { get; set; } = new List(); //Visible only if the story is a video. + + public bool HasAudio { get; set; } //Visible only if the story is a video. + + public double VideoDuration { get; set; } //Visible only if the story is a video. + + #endregion + + public bool CanViewerSave { get; set; } + + public DateTime ExpiringAt { get; set; } + + public bool IsReelMedia { get; set; } + + //public List ReelMentions { get; set; } --- --- //I'll do a test via Fiddler + + //public List StoryLocation { get; set; } + + //public List StoryHashtags { get; set; } //I'll do a test via Fiddler + } +} diff --git a/InstaSharper/Classes/Models/InstaStoryTray.cs b/InstaSharper/Classes/Models/InstaStoryTray.cs new file mode 100644 index 00000000..1bf6ebdb --- /dev/null +++ b/InstaSharper/Classes/Models/InstaStoryTray.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.Models +{ + public class InstaStoryTray + { + public List Tray { get; set; } = new List(); + + public string StoryRankingToken { get; set; } + + //public List Broadcasts { get; set; } = new List(); //No info at this time... I'll check later with Fiddler + + public int StickerVersion { get; set; } + + public string Status { get; set; } + } +} diff --git a/InstaSharper/Classes/Models/MediaVideo.cs b/InstaSharper/Classes/Models/MediaVideo.cs new file mode 100644 index 00000000..2edd854e --- /dev/null +++ b/InstaSharper/Classes/Models/MediaVideo.cs @@ -0,0 +1,23 @@ +namespace InstaSharper.Classes.Models +{ + public class MediaVideo + { + + public MediaVideo(string url, string width, string height, int type) + { + Url = url; + Width = width; + Height = height; + Type = type; + } + + public string Url { get; set; } + + public string Width { get; set; } + + public string Height { get; set; } + + public int Type { get; set; } + + } +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs new file mode 100644 index 00000000..03314ba1 --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs @@ -0,0 +1,120 @@ +using System; +using InstaSharper.Classes.Models; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; + +namespace InstaSharper.Classes.ResponseWrappers +{ + internal class InstaStoryItemResponse + { + [JsonProperty("taken_at")] + public long TakenAt { get; set; } + + [JsonProperty("pk")] + public long Pk { get; set; } + + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("device_timestamp")] + public long DeviceTimeStamp { get; set; } + + [JsonProperty("media_type")] + public InstaMediaType MediaType { get; set; } + + [JsonProperty("code")] + public string Code { get; set; } + + [JsonProperty("client_cache_key")] + public string ClientCacheKey { get; set; } + + [JsonProperty("filter_type")] + public int FilterType { get; set; } + + [JsonProperty("image_versions2")] + public InstaImageCandidatesResponse ImageVersions { get; set; } + + [JsonProperty("original_width")] + public int OriginalWidth { get; set; } + + [JsonProperty("original_height")] + public int OriginalHeight { get; set; } + + [JsonProperty("caption_position")] + public double CaptionPosition { get; set; } + + [JsonProperty("user")] + public InstaUserResponse User { get; set; } + + [JsonProperty("organic_tracking_token")] + public string TrackingToken { get; set; } + + [JsonProperty("like_count")] + public int LikeCount { get; set; } + + [JsonProperty("likers")] + public List Likers { get; set; } + + [JsonProperty("usertags")] + public InstaUserTagListResponse UserTags { get; set; } + + [JsonProperty("carousel_media")] + public InstaCarouselResponse CarouselMedia { get; set; } + + [JsonProperty("has_liked")] + public bool HasLiked { get; set; } + + [JsonProperty("has_more_comments")] + public bool HasMoreComments { get; set; } + + [JsonProperty("max_num_visible_preview_comments")] + public int MaxNumVisiblePreviewComments { get; set; } + + //public InstaComment PreviewComments { get; set; } --- --- //I'll check what is. + + [JsonProperty("comment_count")] + public int CommentCount { get; set; } + + [JsonProperty("comment_disabled")] + public bool CommentsDisabled { get; set; } + + [JsonProperty("caption")] + public InstaCaptionResponse Caption { get; set; } + + [JsonProperty("caption_is_edited")] + public bool CaptionIsEdited { get; set; } //Visible only if the story is an image. + + [JsonProperty("photo_of_you")] + public bool PhotoOfYou { get; set; } + + #region Video + + [JsonProperty("video_versions")] + public InstaVideoCandidatesResponse VideoVersions { get; set; } //Visible only if the story is a video. + + [JsonProperty("has_audio")] + public bool HasAudio { get; set; } //Visible only if the story is a video. + + [JsonProperty("video_duration")] + public double VideoDuration { get; set; } //Visible only if the story is a video. + + #endregion + + [JsonProperty("can_viewer_save")] + public bool CanViewerSave { get; set; } + + [JsonProperty("expiring_at")] + public long ExpiringAt { get; set; } + + [JsonProperty("is_reel_media")] + public bool IsReelMedia { get; set; } + + //public List ReelMentions { get; set; } --- --- //I'll do a test via Fiddler + + //[JsonProperty("story_locations")] + //public List StoryLocation { get; set; } + + //public List StoryHashtags { get; set; } //I'll do a test via Fiddler + } +} diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs index 1e31f442..e4adf1c0 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs @@ -1,4 +1,6 @@ -using Newtonsoft.Json; +using InstaSharper.Classes.Models; +using Newtonsoft.Json; +using System.Collections.Generic; namespace InstaSharper.Classes.ResponseWrappers { @@ -8,7 +10,7 @@ internal class InstaStoryResponse public bool CanReply { get; set; } [JsonProperty("expiring_at")] - public string ExpiringAt { get; set; } + public long ExpiringAt { get; set; } [JsonProperty("user")] public InstaUserResponse User { get; set; } @@ -17,7 +19,7 @@ internal class InstaStoryResponse public string SourceToken { get; set; } [JsonProperty("seen")] - public bool Seen { get; set; } + public double Seen { get; set; } //Should be a DateTime [JsonProperty("latest_reel_media")] public string LatestReelMedia { get; set; } @@ -28,7 +30,19 @@ internal class InstaStoryResponse [JsonProperty("ranked_position")] public int RankedPosition { get; set; } + [JsonProperty("muted")] + public bool Muted { get; set; } + [JsonProperty("seen_ranked_position")] public int SeenRankedPosition { get; set; } + + [JsonProperty("items")] + public List Items { get; set; } + + [JsonProperty("prefetch_count")] + public int PrefetchCount { get; set; } + + [JsonProperty("social_context")] + public string SocialContext { get; set; } } } \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs new file mode 100644 index 00000000..3aef336c --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs @@ -0,0 +1,25 @@ +using InstaSharper.Classes.Models; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.ResponseWrappers +{ + class InstaStoryTrayResponse + { + [JsonProperty("tray")] + public List Tray { get; set; } + + [JsonProperty("story_ranking_token")] + public string StoryRankingToken { get; set; } + + //public List Broadcasts { get; set; } = new List(); //No info at this time... I'll check later with Fiddler + + [JsonProperty("sticker_version")] + public int StickerVersion { get; set; } + + [JsonProperty("status")] + public string Status { get; set; } + } +} diff --git a/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs new file mode 100644 index 00000000..d37f7e51 --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs @@ -0,0 +1,11 @@ +using InstaSharper.Classes.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.ResponseWrappers +{ + class InstaVideoCandidatesResponse : List + { + } +} diff --git a/InstaSharper/Converters/ConvertersFabric.cs b/InstaSharper/Converters/ConvertersFabric.cs index 5b133326..f8e2382c 100644 --- a/InstaSharper/Converters/ConvertersFabric.cs +++ b/InstaSharper/Converters/ConvertersFabric.cs @@ -110,5 +110,20 @@ public static IObjectConverter Get { return new InstaCarouselItemConverter {SourceObject = carouselItem}; } + + public static IObjectConverter GetStoryItemConverter(InstaStoryItemResponse storyItem) + { + return new InstaStoryItemConverter { SourceObject = storyItem }; + } + + public static IObjectConverter GetStoryConverter(InstaStoryResponse storyItem) + { + return new InstaStoryConverter { SourceObject = storyItem }; + } + + public static IObjectConverter GetStoryTrayConverter(InstaStoryTrayResponse storyTray) + { + return new InstaStoryTrayConverter { SourceObject = storyTray }; + } } } \ No newline at end of file diff --git a/InstaSharper/Converters/InstaStoryConverter.cs b/InstaSharper/Converters/InstaStoryConverter.cs index 710a729f..18525a4e 100644 --- a/InstaSharper/Converters/InstaStoryConverter.cs +++ b/InstaSharper/Converters/InstaStoryConverter.cs @@ -21,9 +21,19 @@ public InstaStory Convert() RankedPosition = SourceObject.RankedPosition, Seen = SourceObject.Seen, SeenRankedPosition = SourceObject.SeenRankedPosition, - SourceToken = SourceObject.SourceToken + Muted = SourceObject.Muted, + SourceToken = SourceObject.SourceToken, + PrefetchCount = SourceObject.PrefetchCount, + SocialContext = SourceObject.SocialContext }; - if (SourceObject.User != null) story.User = ConvertersFabric.GetUserConverter(SourceObject.User).Convert(); + + if (SourceObject.User != null) + story.User = ConvertersFabric.GetUserConverter(SourceObject.User).Convert(); + + if (SourceObject.Items?.Count > 0) + foreach (var InstaStory in SourceObject.Items) + story.Items.Add(ConvertersFabric.GetStoryItemConverter(InstaStory).Convert()); + return story; } } diff --git a/InstaSharper/Converters/InstaStoryItemConverter.cs b/InstaSharper/Converters/InstaStoryItemConverter.cs new file mode 100644 index 00000000..cf1e1d40 --- /dev/null +++ b/InstaSharper/Converters/InstaStoryItemConverter.cs @@ -0,0 +1,68 @@ +using System; +using InstaSharper.Classes.Models; +using InstaSharper.Classes.ResponseWrappers; +using InstaSharper.Helpers; + +namespace InstaSharper.Converters +{ + internal class InstaStoryItemConverter : IObjectConverter + { + public InstaStoryItemResponse SourceObject { get; set; } + + public InstaStoryItem Convert() + { + if (SourceObject == null) throw new ArgumentNullException($"Source object"); + var instaStory = new InstaStoryItem + { + CanViewerSave = SourceObject.CanViewerSave, + CaptionIsEdited = SourceObject.CaptionIsEdited, + CaptionPosition = SourceObject.CaptionPosition, + ClientCacheKey = SourceObject.ClientCacheKey, + Code = SourceObject.Code, + CommentCount = SourceObject.CommentCount, + CommentsDisabled = SourceObject.CommentsDisabled, + ExpiringAt = DateTimeHelper.UnixTimestampToDateTime(SourceObject.ExpiringAt), + FilterType = SourceObject.FilterType, + HasAudio = SourceObject.HasAudio, + HasLiked = SourceObject.HasLiked, + HasMoreComments = SourceObject.HasMoreComments, + Id = SourceObject.Id, + IsReelMedia = SourceObject.IsReelMedia, + LikeCount = SourceObject.LikeCount, + MaxNumVisiblePreviewComments = SourceObject.MaxNumVisiblePreviewComments, + MediaType = SourceObject.MediaType, + OriginalHeight = SourceObject.OriginalHeight, + OriginalWidth = SourceObject.OriginalWidth, + PhotoOfYou = SourceObject.PhotoOfYou, + Pk = SourceObject.Pk, + TakenAt = DateTimeHelper.UnixTimestampToDateTime(SourceObject.TakenAt), + TrackingToken = SourceObject.TrackingToken, + VideoDuration = SourceObject.VideoDuration, + VideoVersions = SourceObject.VideoVersions + }; + + if (SourceObject.User != null) + instaStory.User = ConvertersFabric.GetUserConverter(SourceObject.User).Convert(); + + if (SourceObject.Caption != null) + instaStory.Caption = ConvertersFabric.GetCaptionConverter(SourceObject.Caption).Convert(); + + if (SourceObject.Likers?.Count > 0) + foreach (var liker in SourceObject.Likers) + instaStory.Likers.Add(ConvertersFabric.GetUserConverter(liker).Convert()); + + if (SourceObject.CarouselMedia != null) + instaStory.CarouselMedia = ConvertersFabric.GetCarouselConverter(SourceObject.CarouselMedia).Convert(); + + if (SourceObject.UserTags?.In?.Count > 0) + foreach (var tag in SourceObject.UserTags.In) + instaStory.UserTags.Add(ConvertersFabric.GetUserTagConverter(tag).Convert()); + + if (SourceObject.ImageVersions?.Candidates != null) + foreach (var image in SourceObject.ImageVersions.Candidates) + instaStory.Images.Add(new MediaImage(image.Url, int.Parse(image.Width), int.Parse(image.Height))); + + return instaStory; + } + } +} \ No newline at end of file diff --git a/InstaSharper/Converters/InstaStoryTrayConverter.cs b/InstaSharper/Converters/InstaStoryTrayConverter.cs new file mode 100644 index 00000000..444815e7 --- /dev/null +++ b/InstaSharper/Converters/InstaStoryTrayConverter.cs @@ -0,0 +1,28 @@ +using System; +using InstaSharper.Classes.Models; +using InstaSharper.Classes.ResponseWrappers; + +namespace InstaSharper.Converters +{ + internal class InstaStoryTrayConverter : IObjectConverter + { + public InstaStoryTrayResponse SourceObject { get; set; } + + public InstaStoryTray Convert() + { + if (SourceObject == null) throw new ArgumentNullException($"Source object"); + + var storyTray = new InstaStoryTray { + Status = SourceObject.Status, + StickerVersion = SourceObject.StickerVersion, + StoryRankingToken = SourceObject.StoryRankingToken + }; + + if (SourceObject.Tray.Count > 0) + foreach (var story in SourceObject.Tray) + storyTray.Tray.Add(ConvertersFabric.GetStoryConverter(story).Convert()); + + return storyTray; + } + } +} \ No newline at end of file diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 9ae6384d..6e95724a 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -303,5 +303,20 @@ public static Uri GetMediaConfigureUri() throw new Exception("Cant create URI for configuring media"); return instaUri; } + + public static Uri GetStoryTray() + { + if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.GET_STORY_TRAY, out var instaUri)) + throw new Exception("Can't create URI for getting story tray"); + return instaUri; + } + + public static Uri GetUserStoryUri(long userId) + { + if (!Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.GET_USER_STORY, userId), + out var instaUri)) + throw new Exception("Can't create URI for getting user's story"); + return instaUri; + } } } \ No newline at end of file From cff3cb965015950a6d947da93c78917671432375 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sun, 7 May 2017 04:37:42 +0200 Subject: [PATCH 02/17] Upload photo to Instagram Stories Added: upload photo to Instagram Stories --- InstaSharper.Tests/Endpoints/StoryTest.cs | 30 ++++++- InstaSharper/API/IInstaApi.cs | 32 +++++++ InstaSharper/API/InstaApi.cs | 90 +++++++++++++++++++ InstaSharper/API/InstaApiConstants.cs | 4 + .../Classes/Models/InstaStoryMedia.cs | 11 +++ .../InstaStoryMediaResponse.cs | 13 +++ InstaSharper/Converters/ConvertersFabric.cs | 5 ++ .../Converters/InstaStoryMediaConverter.cs | 23 +++++ InstaSharper/Helpers/UriCreator.cs | 7 ++ 9 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 InstaSharper/Classes/Models/InstaStoryMedia.cs create mode 100644 InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs create mode 100644 InstaSharper/Converters/InstaStoryMediaConverter.cs diff --git a/InstaSharper.Tests/Endpoints/StoryTest.cs b/InstaSharper.Tests/Endpoints/StoryTest.cs index 9322e4a2..716d0853 100644 --- a/InstaSharper.Tests/Endpoints/StoryTest.cs +++ b/InstaSharper.Tests/Endpoints/StoryTest.cs @@ -3,7 +3,7 @@ using InstaSharper.Tests.Utils; using Xunit; using Xunit.Abstractions; - +using InstaSharper.Classes.Models; namespace InstaSharper.Tests.Endpoints { @@ -59,5 +59,33 @@ private async void GetUserStory(long userId) Assert.True(result.Succeeded); Assert.NotNull(stories); } + + [RunnableInDebugOnlyFact] + public async void UploadStoryImage() + { + //arrange + var apiInstance = + TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = _username, + Password = _password + }); + + //act + var loginSucceed = TestHelpers.Login(apiInstance, _output); + Assert.True(loginSucceed); + + var mediaImage = new MediaImage + { + Height = 1200, + Width = 640, + URI = new Uri(@"C:\privKey\test.jpg", UriKind.Absolute).LocalPath + }; + var result = await apiInstance.UploadStoryPhotoAsync(mediaImage, "Lake"); + + //assert + Assert.True(result.Succeeded); + Assert.NotNull(result.Value); + } } } diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index f968ec26..c82a3810 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -254,6 +254,22 @@ public interface IInstaApi /// User Id IResult GetUserStory(long userId); + /// + /// Upload story photo + /// + /// Photo to upload + /// Caption + IResult UploadStoryPhoto(MediaImage image, string caption); + + /// + /// Configure story photo + /// + /// Photo to configure + /// Upload id + /// Caption + /// + IResult ConfigureStoryPhoto(MediaImage image, string uploadId, string caption); + #endregion #region Async Members @@ -500,6 +516,22 @@ public interface IInstaApi /// User Id Task> GetUserStoryAsync(long userId); + /// + /// Upload story photo + /// + /// Photo to upload + /// Caption + Task> UploadStoryPhotoAsync(MediaImage image, string caption); + + /// + /// Configure story photo + /// + /// Photo to configure + /// Upload id + /// Caption + /// + Task> ConfigureStoryPhotoAsync(MediaImage image, string uploadId, string caption); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index 26841d39..f90874e1 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -204,6 +204,16 @@ public IResult GetUserStory(long userId) return GetUserStoryAsync(userId).Result; } + public IResult UploadStoryPhoto(MediaImage image, string caption) + { + return UploadStoryPhotoAsync(image, caption).Result; + } + + public IResult ConfigureStoryPhoto(MediaImage image, string uploadId, string caption) + { + return ConfigureStoryPhotoAsync(image, uploadId, caption).Result; + } + #endregion #region async part @@ -1121,6 +1131,86 @@ public async Task> GetUserStoryAsync(long userId) } } + public async Task> UploadStoryPhotoAsync(MediaImage image, string caption) + { + ValidateUser(); + ValidateLoggedIn(); + try + { + var instaUri = UriCreator.GetUploadPhotoUri(); + var uploadId = ApiRequestMessage.GenerateUploadId(); + var requestContent = new MultipartFormDataContent(uploadId) + { + { new StringContent(uploadId), "\"upload_id\"" }, + { new StringContent(_deviceInfo.DeviceGuid.ToString()), "\"_uuid\"" }, + { new StringContent(_user.CsrfToken), "\"_csrftoken\"" }, + { + new StringContent("{\"lib_name\":\"jt\",\"lib_version\":\"1.3.0\",\"quality\":\"87\"}"), + "\"image_compression\"" + } + }; + var imageContent = new ByteArrayContent(File.ReadAllBytes(image.URI)); + imageContent.Headers.Add("Content-Transfer-Encoding", "binary"); + imageContent.Headers.Add("Content-Type", "application/octet-stream"); + requestContent.Add(imageContent, "photo", $"pending_media_{ApiRequestMessage.GenerateUploadId()}.jpg"); + var request = HttpHelper.GetDefaultRequest(HttpMethod.Post, instaUri, _deviceInfo); + request.Content = requestContent; + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) + return await ConfigureStoryPhotoAsync(image, uploadId, caption); + var status = GetBadStatusFromJsonString(json); + return Result.Fail(status.Message, (InstaStoryMedia)null); + } + catch (Exception exception) + { + return Result.Fail(exception.Message, (InstaStoryMedia)null); + } + } + + public async Task> ConfigureStoryPhotoAsync(MediaImage image, string uploadId, string caption) + { + ValidateUser(); + ValidateLoggedIn(); + try + { + var instaUri = UriCreator.GetStoryConfigureUri(); + var androidVersion = + AndroidVersion.FromString(_deviceInfo.FirmwareFingerprint.Split('/')[2].Split(':')[1]); + if (androidVersion == null) + return Result.Fail("Unsupported android version", (InstaStoryMedia)null); + var data = new JObject + { + {"_uuid", _deviceInfo.DeviceGuid.ToString()}, + {"_uid", _user.LoggedInUder.Pk}, + {"_csrftoken", _user.CsrfToken}, + {"source_type", "1"}, + {"caption", caption}, + {"upload_id", uploadId}, + {"edits", new JObject { } }, + {"disable_comments", false }, + {"configure_mode", 1}, + {"camera_position", "unknown" } + + }; + var request = HttpHelper.GetSignedRequest(HttpMethod.Post, instaUri, _deviceInfo, data); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) + { + var mediaResponse = JsonConvert.DeserializeObject(json); + var converter = ConvertersFabric.GetStoryMediaConverter(mediaResponse); + return Result.Success(converter.Convert()); + } + var status = GetBadStatusFromJsonString(json); + return Result.Fail(status.Message, (InstaStoryMedia)null); + } + catch (Exception exception) + { + return Result.Fail(exception.Message, (InstaStoryMedia)null); + } + } + #endregion #region private part diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index cbe34a9c..96a544a2 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -46,8 +46,12 @@ internal static class InstaApiConstants public const string DELETE_COMMENT = API_SUFFIX + "/v1/media/{0}/comment/{1}/delete/"; public const string UPLOAD_PHOTO = API_SUFFIX + "/v1/upload/photo/"; public const string MEDIA_CONFIGURE = API_SUFFIX + "/v1/media/configure/"; + + public const string LOCATION_SEARCH = API_SUFFIX + "/v1/location_search/"; + public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; + public const string STORY_CONFIGURE = API_SUFFIX + "/v1/media/configure_to_reel/"; public const string HEADER_USER_AGENT = "User-Agent"; diff --git a/InstaSharper/Classes/Models/InstaStoryMedia.cs b/InstaSharper/Classes/Models/InstaStoryMedia.cs new file mode 100644 index 00000000..4d93cfb6 --- /dev/null +++ b/InstaSharper/Classes/Models/InstaStoryMedia.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.Models +{ + public class InstaStoryMedia + { + public InstaStoryItem Media { get; set; } + } +} diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs new file mode 100644 index 00000000..2f6ff04a --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.ResponseWrappers +{ + class InstaStoryMediaResponse + { + [JsonProperty("media")] + public InstaStoryItemResponse Media { get; set; } + } +} diff --git a/InstaSharper/Converters/ConvertersFabric.cs b/InstaSharper/Converters/ConvertersFabric.cs index f8e2382c..8edb539f 100644 --- a/InstaSharper/Converters/ConvertersFabric.cs +++ b/InstaSharper/Converters/ConvertersFabric.cs @@ -125,5 +125,10 @@ public static IObjectConverter GetStoryT { return new InstaStoryTrayConverter { SourceObject = storyTray }; } + + public static IObjectConverter GetStoryMediaConverter(InstaStoryMediaResponse storyMedia) + { + return new InstaStoryMediaConverter { SourceObject = storyMedia }; + } } } \ No newline at end of file diff --git a/InstaSharper/Converters/InstaStoryMediaConverter.cs b/InstaSharper/Converters/InstaStoryMediaConverter.cs new file mode 100644 index 00000000..03973ea6 --- /dev/null +++ b/InstaSharper/Converters/InstaStoryMediaConverter.cs @@ -0,0 +1,23 @@ +using InstaSharper.Classes.Models; +using InstaSharper.Classes.ResponseWrappers; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Converters +{ + class InstaStoryMediaConverter : IObjectConverter + { + public InstaStoryMediaResponse SourceObject { get; set; } + + public InstaStoryMedia Convert() + { + var instaStoryMedia = new InstaStoryMedia + { + Media = ConvertersFabric.GetStoryItemConverter(SourceObject.Media).Convert() + }; + + return instaStoryMedia; + } + } +} diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 6e95724a..c124c517 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -318,5 +318,12 @@ public static Uri GetUserStoryUri(long userId) throw new Exception("Can't create URI for getting user's story"); return instaUri; } + + public static Uri GetStoryConfigureUri() + { + if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.STORY_CONFIGURE, out var instaUri)) + throw new Exception("Can't create URI for getting user's story"); + return instaUri; + } } } \ No newline at end of file From 7f242ff91e11db228c72d1cb6ef0defd62c6692e Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sun, 7 May 2017 04:44:54 +0200 Subject: [PATCH 03/17] Upload photo to Instagram Stories Added: upload photo to Instagram Stories + Little edit --- InstaSharper/API/InstaApi.cs | 4 ---- InstaSharper/Helpers/UriCreator.cs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index f90874e1..f4a6009d 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -1175,10 +1175,6 @@ public async Task> ConfigureStoryPhotoAsync(MediaImage try { var instaUri = UriCreator.GetStoryConfigureUri(); - var androidVersion = - AndroidVersion.FromString(_deviceInfo.FirmwareFingerprint.Split('/')[2].Split(':')[1]); - if (androidVersion == null) - return Result.Fail("Unsupported android version", (InstaStoryMedia)null); var data = new JObject { {"_uuid", _deviceInfo.DeviceGuid.ToString()}, diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index c124c517..2656c000 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -322,7 +322,7 @@ public static Uri GetUserStoryUri(long userId) public static Uri GetStoryConfigureUri() { if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.STORY_CONFIGURE, out var instaUri)) - throw new Exception("Can't create URI for getting user's story"); + throw new Exception("Can't create URI for configuring story media"); return instaUri; } } From 0222c75d2e890a0f06c27dbd2f687b0ce1d80206 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sun, 7 May 2017 19:53:12 +0200 Subject: [PATCH 04/17] Change password Added: Change password --- InstaSharper.Tests/Endpoints/StoryTest.cs | 8 +-- InstaSharper.Tests/Endpoints/UserInfoTest.cs | 18 +++++++ InstaSharper/API/IInstaApi.cs | 25 ++++++++-- InstaSharper/API/InstaApi.cs | 50 +++++++++++++++++++ InstaSharper/API/InstaApiConstants.cs | 7 +-- .../BadStatusErrorsResponse.cs | 20 ++++++++ InstaSharper/Helpers/UriCreator.cs | 7 +++ 7 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs diff --git a/InstaSharper.Tests/Endpoints/StoryTest.cs b/InstaSharper.Tests/Endpoints/StoryTest.cs index 716d0853..259d5363 100644 --- a/InstaSharper.Tests/Endpoints/StoryTest.cs +++ b/InstaSharper.Tests/Endpoints/StoryTest.cs @@ -8,7 +8,7 @@ namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - class StoryTest + public class StoryTest { private readonly ITestOutputHelper _output; private readonly string _password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); @@ -20,7 +20,7 @@ public StoryTest(ITestOutputHelper output) } [RunnableInDebugOnlyFact] - private async void GetStoryTray() + private async void GetStoryTrayTest() { //arrange var apiInstance = @@ -41,7 +41,7 @@ private async void GetStoryTray() [RunnableInDebugOnlyTheory] [InlineData(1129166614)] - private async void GetUserStory(long userId) + private async void GetUserStoryTest(long userId) { //arrange var apiInstance = @@ -61,7 +61,7 @@ private async void GetUserStory(long userId) } [RunnableInDebugOnlyFact] - public async void UploadStoryImage() + public async void UploadStoryImageTest() { //arrange var apiInstance = diff --git a/InstaSharper.Tests/Endpoints/UserInfoTest.cs b/InstaSharper.Tests/Endpoints/UserInfoTest.cs index c87d4820..badf8b05 100644 --- a/InstaSharper.Tests/Endpoints/UserInfoTest.cs +++ b/InstaSharper.Tests/Endpoints/UserInfoTest.cs @@ -78,5 +78,23 @@ public async void SetAccountPrivacyTest() Assert.True(resultSetPublic.Succeeded); Assert.NotNull(resultSetPrivate.Value); } + + [RunnableInDebugOnlyFact] + public async void ChangePasswordTest() + { + //arrange + var apiInstance = + TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = _username, + Password = _password + }); + //act + if (!TestHelpers.Login(apiInstance, _output)) return; + var resultChangePassword = await apiInstance.ChangePasswordAsync("oldPassword", "newPassword"); + //assert + Assert.True(resultChangePassword.Succeeded); + Assert.NotNull(resultChangePassword.Value); + } } } \ No newline at end of file diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index c82a3810..de166709 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -178,28 +178,28 @@ public interface IInstaApi /// Like instagram media by id /// /// Media Id - /// True i success + /// True if success IResult LikeMedia(string mediaId); /// /// Like instagram media by id /// /// Media Id - /// True i success + /// True if success IResult UnlikeMedia(string mediaId); /// /// Follow user by its by id /// /// User Id - /// True i success + /// True if success IResult FollowUser(long userId); /// /// Stop follow user by its by id /// /// User Id - /// True i success + /// True if success IResult UnFollowUser(long userId); /// @@ -267,9 +267,16 @@ public interface IInstaApi /// Photo to configure /// Upload id /// Caption - /// IResult ConfigureStoryPhoto(MediaImage image, string uploadId, string caption); + /// + /// Change password + /// + /// The old password + /// The new password (shouldn't be the same old password, and should be a password you never used here) + /// Return true if the password is changed + IResult ChangePassword(string oldPassword, string newPassword); + #endregion #region Async Members @@ -532,6 +539,14 @@ public interface IInstaApi /// Task> ConfigureStoryPhotoAsync(MediaImage image, string uploadId, string caption); + /// + /// Change password + /// + /// The old password + /// The new password (shouldn't be the same old password, and should be a password you never used here) + /// Return true if the password is changed + Task> ChangePasswordAsync(string oldPassword, string newPassword); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index f4a6009d..d85aa93b 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -214,6 +214,11 @@ public IResult ConfigureStoryPhoto(MediaImage image, string upl return ConfigureStoryPhotoAsync(image, uploadId, caption).Result; } + public IResult ChangePassword(string oldPassword, string newPassword) + { + return ChangePasswordAsync(oldPassword, newPassword).Result; + } + #endregion #region async part @@ -1207,6 +1212,51 @@ public async Task> ConfigureStoryPhotoAsync(MediaImage } } + public async Task> ChangePasswordAsync(string oldPassword, string newPassword) + { + ValidateUser(); + ValidateLoggedIn(); + + if (oldPassword == newPassword) + return Result.Fail("The old password should not the same of the new password", false); + + try + { + var changePasswordUri = UriCreator.GetChangePasswordUri(); + + var data = new JObject + { + {"_uuid", _deviceInfo.DeviceGuid.ToString()}, + {"_uid", _user.LoggedInUder.Pk}, + {"_csrftoken", _user.CsrfToken}, + {"old_password", oldPassword}, + {"new_password1", newPassword}, + {"new_password2", newPassword} + }; + + var request = HttpHelper.GetSignedRequest(HttpMethod.Get, changePasswordUri, _deviceInfo, data); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == HttpStatusCode.OK) + { + return Result.Success(true); //If status code is OK, then the password is surely changed + } + else + { + + var error = JsonConvert.DeserializeObject(json); + string errors = ""; + error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); + return Result.Fail(errors, false); + } + + } + catch (Exception exception) + { + return Result.Fail(exception.Message, false); + } + } + #endregion #region private part diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index 96a544a2..e17fe659 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -17,6 +17,7 @@ internal static class InstaApiConstants public const string API_SUFFIX = "/api"; public const string SEARCH_USERS = API_SUFFIX + "/v1/users/search"; public const string ACCOUNTS_LOGIN = API_SUFFIX + "/v1/accounts/login/"; + public const string CHANGE_PASSWORD = API_SUFFIX + "/v1/accounts/change_password/"; /* implementing */ public const string ACCOUNTS_LOGOUT = API_SUFFIX + "/v1/accounts/logout/"; public const string EXPLORE = API_SUFFIX + "/v1/discover/explore/"; public const string TIMELINEFEED = API_SUFFIX + "/v1/feed/timeline"; @@ -46,13 +47,13 @@ internal static class InstaApiConstants public const string DELETE_COMMENT = API_SUFFIX + "/v1/media/{0}/comment/{1}/delete/"; public const string UPLOAD_PHOTO = API_SUFFIX + "/v1/upload/photo/"; public const string MEDIA_CONFIGURE = API_SUFFIX + "/v1/media/configure/"; - - public const string LOCATION_SEARCH = API_SUFFIX + "/v1/location_search/"; - public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; public const string STORY_CONFIGURE = API_SUFFIX + "/v1/media/configure_to_reel/"; + public const string LOCATION_SEARCH = API_SUFFIX + "/v1/location_search/"; /* To implement */ + + public const string HEADER_USER_AGENT = "User-Agent"; public const string USER_AGENT = diff --git a/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs b/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs new file mode 100644 index 00000000..a7cb5a89 --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs @@ -0,0 +1,20 @@ +using InstaSharper.Classes.ResponseWrappers.BaseResponse; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.ResponseWrappers +{ + public class BadStatusErrorsResponse : BaseStatusResponse + { + [JsonProperty("message")] + public MessageErrorsResponse Message { get; set; } + } + + public class MessageErrorsResponse + { + [JsonProperty("errors")] + public List Errors { get; set; } + } +} diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 2656c000..1ebc1d54 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -325,5 +325,12 @@ public static Uri GetStoryConfigureUri() throw new Exception("Can't create URI for configuring story media"); return instaUri; } + + public static Uri GetChangePasswordUri() + { + if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.CHANGE_PASSWORD, out var instaUri)) + throw new Exception("Can't create URI for configuring story media"); + return instaUri; + } } } \ No newline at end of file From a355267dca9c851de64b13e0897bf542d97a52a8 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sun, 7 May 2017 19:55:36 +0200 Subject: [PATCH 05/17] Change password Little fix --- InstaSharper/API/InstaApiConstants.cs | 2 +- InstaSharper/Helpers/UriCreator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index e17fe659..53018c3f 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -17,7 +17,7 @@ internal static class InstaApiConstants public const string API_SUFFIX = "/api"; public const string SEARCH_USERS = API_SUFFIX + "/v1/users/search"; public const string ACCOUNTS_LOGIN = API_SUFFIX + "/v1/accounts/login/"; - public const string CHANGE_PASSWORD = API_SUFFIX + "/v1/accounts/change_password/"; /* implementing */ + public const string CHANGE_PASSWORD = API_SUFFIX + "/v1/accounts/change_password/"; public const string ACCOUNTS_LOGOUT = API_SUFFIX + "/v1/accounts/logout/"; public const string EXPLORE = API_SUFFIX + "/v1/discover/explore/"; public const string TIMELINEFEED = API_SUFFIX + "/v1/feed/timeline"; diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 1ebc1d54..9b95cdb6 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -329,7 +329,7 @@ public static Uri GetStoryConfigureUri() public static Uri GetChangePasswordUri() { if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.CHANGE_PASSWORD, out var instaUri)) - throw new Exception("Can't create URI for configuring story media"); + throw new Exception("Can't create URI for changing password"); return instaUri; } } From ff3b34fb98a8f6c1534a3a68118790380c211639 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Mon, 8 May 2017 22:35:58 +0200 Subject: [PATCH 06/17] Delete photo & video Added: Delete media (photo or video) --- InstaSharper.Tests/Endpoints/MediaTest.cs | 38 +++++++++++++++ InstaSharper/API/IInstaApi.cs | 16 +++++++ InstaSharper/API/InstaApi.cs | 47 ++++++++++++++++++- InstaSharper/API/InstaApiConstants.cs | 1 + .../ResponseWrappers/DeleteResponse.cs | 13 +++++ InstaSharper/Helpers/UriCreator.cs | 8 ++++ InstaSharper/InstaSharper.csproj | 6 ++- 7 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs diff --git a/InstaSharper.Tests/Endpoints/MediaTest.cs b/InstaSharper.Tests/Endpoints/MediaTest.cs index ad9cd2d5..f0e79587 100644 --- a/InstaSharper.Tests/Endpoints/MediaTest.cs +++ b/InstaSharper.Tests/Endpoints/MediaTest.cs @@ -4,6 +4,7 @@ using InstaSharper.Tests.Utils; using Xunit; using Xunit.Abstractions; +using InstaSharper.Classes.Models; namespace InstaSharper.Tests.Endpoints { @@ -134,7 +135,44 @@ public async void PostDeleteCommentTest(string mediaId) Assert.True(postResult.Succeeded); Assert.Equal(text, postResult.Value.Text); Assert.True(delResult.Succeeded); + } + [Theory] + [InlineData("1510405963000000025_1414585238", InstaMediaType.Image)] + public async void DeleteMediaPhotoTest(string mediaId, InstaMediaType mediaType) + { + //arrange + var username = "thisidlin"; + var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); + var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = username, + Password = password + }); + //act + if (!TestHelpers.Login(apiInstance, _output)) return; + var deleteMediaVideo = await apiInstance.DeleteMediaAsync(mediaId, mediaType); + //assert + Assert.False(deleteMediaVideo.Value); //As the media doesn't exists + } + + [Theory] + [InlineData("1510414591769980888_1414585238", InstaMediaType.Video)] + public async void DeleteMediaVideoTest(string mediaId, InstaMediaType mediaType) + { + //arrange + var username = "thisidlin"; + var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); + var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = username, + Password = password + }); + //act + if (!TestHelpers.Login(apiInstance, _output)) return; + var deleteMediaVideo = await apiInstance.DeleteMediaAsync(mediaId, mediaType); + //assert + Assert.True(deleteMediaVideo.Value); } } } \ No newline at end of file diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index de166709..68a7acca 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -277,6 +277,14 @@ public interface IInstaApi /// Return true if the password is changed IResult ChangePassword(string oldPassword, string newPassword); + /// + /// Delete a media (photo or video) + /// + /// The media ID + /// The type of the media + /// Return true if the media is deleted + IResult DeleteMedia(string mediaId, InstaMediaType mediaType); + #endregion #region Async Members @@ -547,6 +555,14 @@ public interface IInstaApi /// Return true if the password is changed Task> ChangePasswordAsync(string oldPassword, string newPassword); + /// + /// Delete a media (photo or video) + /// + /// The media ID + /// The type of the media + /// Return true if the media is deleted + Task> DeleteMediaAsync(string mediaId, InstaMediaType mediaType); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index d85aa93b..fb759306 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -219,6 +219,11 @@ public IResult ChangePassword(string oldPassword, string newPassword) return ChangePasswordAsync(oldPassword, newPassword).Result; } + public IResult DeleteMedia(string mediaId, InstaMediaType mediaType) + { + return DeleteMediaAsync(mediaId, mediaType).Result; + } + #endregion #region async part @@ -1257,6 +1262,47 @@ public async Task> ChangePasswordAsync(string oldPassword, string } } + public async Task> DeleteMediaAsync(string mediaId, InstaMediaType mediaType) + { + ValidateUser(); + ValidateLoggedIn(); + + try + { + var deleteMediaUri = UriCreator.GetDeleteMediaUri(mediaId, mediaType); + + var data = new JObject + { + {"_uuid", _deviceInfo.DeviceGuid.ToString()}, + {"_uid", _user.LoggedInUder.Pk}, + {"_csrftoken", _user.CsrfToken}, + {"media_id", mediaId} + }; + + var request = HttpHelper.GetSignedRequest(HttpMethod.Get, deleteMediaUri, _deviceInfo, data); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == HttpStatusCode.OK) + { + var deletedResponse = JsonConvert.DeserializeObject(json); + return Result.Success(deletedResponse.IsDeleted); + } + else + { + + var error = JsonConvert.DeserializeObject(json); + string errors = ""; + error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); + return Result.Fail(errors, false); + } + + } + catch (Exception exception) + { + return Result.Fail(exception.Message, false); + } + } + #endregion #region private part @@ -1478,7 +1524,6 @@ private async Task> FollowUnfollowUserInternal(lo return Result.Fail(exception.Message, (InstaFriendshipStatus) null); } } - #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index 53018c3f..d2802263 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -47,6 +47,7 @@ internal static class InstaApiConstants public const string DELETE_COMMENT = API_SUFFIX + "/v1/media/{0}/comment/{1}/delete/"; public const string UPLOAD_PHOTO = API_SUFFIX + "/v1/upload/photo/"; public const string MEDIA_CONFIGURE = API_SUFFIX + "/v1/media/configure/"; + public const string DELETE_MEDIA = API_SUFFIX + "/v1/media/{0}/delete/?media_type={1}"; public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; public const string STORY_CONFIGURE = API_SUFFIX + "/v1/media/configure_to_reel/"; diff --git a/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs b/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs new file mode 100644 index 00000000..32a24ff3 --- /dev/null +++ b/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace InstaSharper.Classes.ResponseWrappers +{ + class DeleteResponse : BaseResponse.BaseStatusResponse + { + [JsonProperty("did_delete")] + public bool IsDeleted { get; set; } + } +} diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 9b95cdb6..2ea584f9 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -1,5 +1,6 @@ using System; using InstaSharper.API; +using InstaSharper.Classes.Models; namespace InstaSharper.Helpers { @@ -332,5 +333,12 @@ public static Uri GetChangePasswordUri() throw new Exception("Can't create URI for changing password"); return instaUri; } + + public static Uri GetDeleteMediaUri(string mediaId, InstaMediaType mediaType) + { + if (!Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.DELETE_MEDIA, mediaId, (int)mediaType), out var instaUri)) + throw new Exception("Can't create URI for deleting media"); + return instaUri; + } } } \ No newline at end of file diff --git a/InstaSharper/InstaSharper.csproj b/InstaSharper/InstaSharper.csproj index 1643dba4..c074603e 100644 --- a/InstaSharper/InstaSharper.csproj +++ b/InstaSharper/InstaSharper.csproj @@ -3,7 +3,7 @@ 1.2.4 netstandard1.6;net452 - true + True InstaSharper InstaSharper 1.6.0 @@ -13,6 +13,10 @@ false + + + + From fb245915720400812c24fcad2e23bc39258f7d1b Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Tue, 9 May 2017 22:53:20 +0300 Subject: [PATCH 07/17] readme update --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e7f5717d..f256f116 100644 --- a/README.md +++ b/README.md @@ -63,21 +63,21 @@ Currently the library supports following coverage of the following Instagram API - [x] Upload photo - [ ] Get followings list +- [ ] Delete media (photo/video) +- [ ] Upload story (photo) +- [ ] Change password * Get user list autocomplete * Register new user * Get megaphone log * Explore feed * Upload video -* Upload story * Get full account backup * Send direct message * Edit media -* Delete media * Share media -* Change password -######for more details please check [Project roadmap](https://github.com/a-legotin/InstaSharper/wiki/Project-roadmap/_edit) +###### for more details please check [Project roadmap](https://github.com/a-legotin/InstaSharper/wiki/Project-roadmap/_edit) ## Easy to use #### Use builder to get Insta API instance: @@ -122,7 +122,7 @@ IResult feed = await api.GetUserFeedAsync(); IResult postResult = await apiInstance.CommentMediaAsync("1234567891234567891_123456789", "Hi there!"); ``` -#####for more samples you can look for [Examples folder](https://github.com/a-legotin/InstaSharper/tree/master/InstaSharper.Examples) +##### for more samples you can look at [Examples folder](https://github.com/a-legotin/InstaSharper/tree/master/InstaSharper.Examples) #### [Why two separate repos with same mission?](https://github.com/a-legotin/InstagramAPI-Web/wiki/Difference-between-API-Web-and-just-API-repositories) From 63cd702be653c518680923e898fddfc39e33ae0f Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Wed, 10 May 2017 14:51:32 +0300 Subject: [PATCH 08/17] Improved error message when logging in --- InstaSharper/API/InstaApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index d85aa93b..e202134f 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -272,7 +272,7 @@ public async Task> LoginAsync() if (loginInfo.ErrorType == "Sorry, too many requests.Please try again later") return Result.Fail("Please try again later, maximum amount of requests reached", ResponseType.LoginRequired, false); - return Result.Fail(loginInfo.Message, false); + return Result.Fail($"{loginInfo.Message}, error type: {loginInfo.ErrorType}", false); } } catch (Exception exception) From c0b6b1685c90e8b2a6e08135dc17114689a3ccb1 Mon Sep 17 00:00:00 2001 From: ADeltaX Date: Sun, 14 May 2017 01:09:08 +0200 Subject: [PATCH 09/17] Edit media (photo/video) Edit's the caption text of a media. --- InstaSharper.Tests/Endpoints/MediaTest.cs | 23 +++++++++++-- InstaSharper/API/IInstaApi.cs | 16 +++++++++ InstaSharper/API/InstaApi.cs | 42 +++++++++++++++++++++++ InstaSharper/API/InstaApiConstants.cs | 1 + InstaSharper/Helpers/UriCreator.cs | 7 ++++ 5 files changed, 87 insertions(+), 2 deletions(-) diff --git a/InstaSharper.Tests/Endpoints/MediaTest.cs b/InstaSharper.Tests/Endpoints/MediaTest.cs index f0e79587..de852a43 100644 --- a/InstaSharper.Tests/Endpoints/MediaTest.cs +++ b/InstaSharper.Tests/Endpoints/MediaTest.cs @@ -151,9 +151,9 @@ public async void DeleteMediaPhotoTest(string mediaId, InstaMediaType mediaType) }); //act if (!TestHelpers.Login(apiInstance, _output)) return; - var deleteMediaVideo = await apiInstance.DeleteMediaAsync(mediaId, mediaType); + var deleteMediaPhoto = await apiInstance.DeleteMediaAsync(mediaId, mediaType); //assert - Assert.False(deleteMediaVideo.Value); //As the media doesn't exists + Assert.False(deleteMediaPhoto.Value); //As the media doesn't exists } [Theory] @@ -174,5 +174,24 @@ public async void DeleteMediaVideoTest(string mediaId, InstaMediaType mediaType) //assert Assert.True(deleteMediaVideo.Value); } + + [Theory] + [InlineData("1513736003209429255_1414585238", "Hello!")] + public async void EditMediaTest(string mediaId, string caption) + { + //arrange + var username = "thisidlin"; + var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); + var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = username, + Password = password + }); + //act + if (!TestHelpers.Login(apiInstance, _output)) return; + var editMedia = await apiInstance.EditMediaAsync(mediaId, caption); + //assert + Assert.True(editMedia.Value); + } } } \ No newline at end of file diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index 68a7acca..b1c5c605 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -285,6 +285,14 @@ public interface IInstaApi /// Return true if the media is deleted IResult DeleteMedia(string mediaId, InstaMediaType mediaType); + /// + /// Edit the caption of the media (photo/video) + /// + /// The media ID + /// The new caption + /// Return true if everything is ok + IResult EditMedia(string mediaId, string caption); + #endregion #region Async Members @@ -563,6 +571,14 @@ public interface IInstaApi /// Return true if the media is deleted Task> DeleteMediaAsync(string mediaId, InstaMediaType mediaType); + /// + /// Edit the caption of the media (photo/video) + /// + /// The media ID + /// The new caption + /// Return true if everything is ok + Task> EditMediaAsync(string mediaId, string caption); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index fb759306..47ef6bbc 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -224,6 +224,11 @@ public IResult DeleteMedia(string mediaId, InstaMediaType mediaType) return DeleteMediaAsync(mediaId, mediaType).Result; } + public IResult EditMedia(string mediaId, string caption) + { + return EditMediaAsync(mediaId, caption).Result; + } + #endregion #region async part @@ -1303,6 +1308,43 @@ public async Task> DeleteMediaAsync(string mediaId, InstaMediaType } } + public async Task> EditMediaAsync(string mediaId, string caption) + { + ValidateUser(); + ValidateLoggedIn(); + + try + { + var editMediaUri = UriCreator.GetEditMediaUri(mediaId); + + var data = new JObject + { + {"_uuid", _deviceInfo.DeviceGuid.ToString()}, + {"_uid", _user.LoggedInUder.Pk}, + {"_csrftoken", _user.CsrfToken}, + {"caption_text", caption} + }; + + var request = HttpHelper.GetSignedRequest(HttpMethod.Get, editMediaUri, _deviceInfo, data); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == HttpStatusCode.OK) + { + return Result.Success(true); //Technically Instagram returns the InstaMediaItem, but it is useless in our case, at this time. + } //As the edited thing is simply a caption. No more. + else + { + var error = JsonConvert.DeserializeObject(json); + return Result.Fail(error.Message, false); + } + + } + catch (Exception exception) + { + return Result.Fail(exception.Message, false); + } + } + #endregion #region private part diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index d2802263..809365ec 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -48,6 +48,7 @@ internal static class InstaApiConstants public const string UPLOAD_PHOTO = API_SUFFIX + "/v1/upload/photo/"; public const string MEDIA_CONFIGURE = API_SUFFIX + "/v1/media/configure/"; public const string DELETE_MEDIA = API_SUFFIX + "/v1/media/{0}/delete/?media_type={1}"; + public const string EDIT_MEDIA = API_SUFFIX + "/v1/media/{0}/edit_media/"; public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; public const string STORY_CONFIGURE = API_SUFFIX + "/v1/media/configure_to_reel/"; diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index 2ea584f9..d634643d 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -340,5 +340,12 @@ public static Uri GetDeleteMediaUri(string mediaId, InstaMediaType mediaType) throw new Exception("Can't create URI for deleting media"); return instaUri; } + + public static Uri GetEditMediaUri(string mediaId) + { + if (!Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.EDIT_MEDIA, mediaId), out var instaUri)) + throw new Exception("Can't create URI for editing media"); + return instaUri; + } } } \ No newline at end of file From 7e006bde057a37bf7b88d87466148f85c87cb3db Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Thu, 25 May 2017 19:18:01 +0300 Subject: [PATCH 10/17] Message improved --- InstaSharper/API/InstaApi.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index e202134f..5eed9ea2 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -458,7 +458,8 @@ public async Task> GetUserAsync(string username) var converter = ConvertersFabric.GetUserConverter(user); return Result.Success(converter.Convert()); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUser) null); + var badResponse = GetBadStatusFromJsonString(json); + return Result.Fail($"{badResponse.Message}, {badResponse.ErrorType}", (InstaUser) null); } From b0c07051bd01cdaab0ddfa18d967d46b08d7ab9e Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Thu, 8 Jun 2017 18:18:57 +0300 Subject: [PATCH 11/17] Improved logging for login stuff --- InstaSharper.Tests/Endpoints/AuthTest.cs | 2 +- InstaSharper.Tests/Utils/TestHelpers.cs | 14 ++- InstaSharper/API/InstaApi.cs | 103 ++++++++++++----------- InstaSharper/Classes/ResponseType.cs | 3 +- InstaSharper/Classes/Result.cs | 2 +- InstaSharper/Classes/ResultInfo.cs | 3 +- InstaSharper/Helpers/InstaProxy.cs | 29 +++++++ 7 files changed, 100 insertions(+), 56 deletions(-) create mode 100644 InstaSharper/Helpers/InstaProxy.cs diff --git a/InstaSharper.Tests/Endpoints/AuthTest.cs b/InstaSharper.Tests/Endpoints/AuthTest.cs index 76951171..19b06db9 100644 --- a/InstaSharper.Tests/Endpoints/AuthTest.cs +++ b/InstaSharper.Tests/Endpoints/AuthTest.cs @@ -38,13 +38,13 @@ public async void UserLoginSuccessTest() { var username = "alex_codegarage"; var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); + var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData { UserName = username, Password = password }); Assert.False(apiInstance.IsUserAuthenticated); - var loginResult = await apiInstance.LoginAsync(); Assert.True(loginResult.Succeeded); Assert.True(apiInstance.IsUserAuthenticated); diff --git a/InstaSharper.Tests/Utils/TestHelpers.cs b/InstaSharper.Tests/Utils/TestHelpers.cs index 409e6f1a..ad2975e8 100644 --- a/InstaSharper.Tests/Utils/TestHelpers.cs +++ b/InstaSharper.Tests/Utils/TestHelpers.cs @@ -1,6 +1,8 @@ -using InstaSharper.API; +using System.Net.Http; +using InstaSharper.API; using InstaSharper.API.Builder; using InstaSharper.Classes; +using InstaSharper.Helpers; using Xunit.Abstractions; namespace InstaSharper.Tests.Utils @@ -25,6 +27,16 @@ public static IInstaApi GetDefaultInstaApiInstance(UserSessionData user) return apiInstance; } + public static IInstaApi GetProxifiedInstaApiInstance(UserSessionData user, InstaProxy proxy) + { + var handler = new HttpClientHandler { Proxy = proxy }; + var apiInstance = new InstaApiBuilder() + .UseHttpClientHandler(handler) + .SetUser(user) + .Build(); + return apiInstance; + } + public static bool Login(IInstaApi apiInstance, ITestOutputHelper output) { var loginResult = apiInstance.Login(); diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index 47ef6bbc..f6b3c973 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -1,23 +1,22 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; -using System.Security.Cryptography; using System.Threading.Tasks; using InstaSharper.Classes; using InstaSharper.Classes.Android.DeviceInfo; using InstaSharper.Classes.Models; +using InstaSharper.Classes.ResponseWrappers; +using InstaSharper.Classes.ResponseWrappers.BaseResponse; using InstaSharper.Converters; using InstaSharper.Converters.Json; using InstaSharper.Helpers; using InstaSharper.Logger; using Newtonsoft.Json; -using InstaRecentActivityConverter = InstaSharper.Converters.Json.InstaRecentActivityConverter; -using InstaSharper.Classes.ResponseWrappers; -using InstaSharper.Classes.ResponseWrappers.BaseResponse; using Newtonsoft.Json.Linq; -using System.IO; +using InstaRecentActivityConverter = InstaSharper.Converters.Json.InstaRecentActivityConverter; namespace InstaSharper.API { @@ -282,6 +281,8 @@ public async Task> LoginAsync() if (loginInfo.ErrorType == "Sorry, too many requests.Please try again later") return Result.Fail("Please try again later, maximum amount of requests reached", ResponseType.LoginRequired, false); + if (loginInfo.ErrorType == "sentry_block") + return Result.Fail("Sentry block. You got blocked by Instagram.", ResponseType.SentryBlock, false); return Result.Fail(loginInfo.Message, false); } } @@ -329,7 +330,7 @@ public async Task> GetUserTimelineFeedAsync(int maxPages = 0) var json = await response.Content.ReadAsStringAsync(); var feed = new InstaFeed(); if (response.StatusCode != HttpStatusCode.OK) - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeed) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeed)null); var feedResponse = JsonConvert.DeserializeObject(json, new InstaFeedResponseDataConverter()); var converter = ConvertersFabric.GetFeedConverter(feedResponse); @@ -364,7 +365,7 @@ public async Task> GetExploreFeedAsync(int maxPages = 0) var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); var exploreFeed = new InstaFeed(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaFeed) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaFeed)null); var mediaResponse = JsonConvert.DeserializeObject(json, new InstaMediaListDataConverter()); exploreFeed.Medias.AddRange( @@ -381,7 +382,7 @@ public async Task> GetExploreFeedAsync(int maxPages = 0) } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaFeed) null); + return Result.Fail(exception.Message, (InstaFeed)null); } } @@ -417,7 +418,7 @@ public async Task> GetUserMediaAsync(string username, in } return Result.Success(mediaList); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMediaList) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMediaList)null); } public async Task> GetMediaByIdAsync(string mediaId) @@ -440,7 +441,7 @@ public async Task> GetMediaByIdAsync(string mediaId) var converter = ConvertersFabric.GetSingleMediaConverter(mediaResponse.Medias.FirstOrDefault()); return Result.Success(converter.Convert()); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMedia) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMedia)null); } public async Task> GetUserAsync(string username) @@ -468,7 +469,7 @@ public async Task> GetUserAsync(string username) var converter = ConvertersFabric.GetUserConverter(user); return Result.Success(converter.Convert()); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUser) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUser)null); } @@ -495,7 +496,7 @@ public async Task> GetCurrentUserAsync() return Result.Success(userConverted); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUser) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUser)null); } public async Task> GetTagFeedAsync(string tag, int maxPages = 0) @@ -530,7 +531,7 @@ public async Task> GetTagFeedAsync(string tag, int maxPages = } return Result.Success(tagFeed); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeed) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeed)null); } public async Task> GetUserFollowersAsync(string username, int maxPages = 0) @@ -546,10 +547,10 @@ public async Task> GetUserFollowersAsync(string username, var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); var followers = new InstaUserList(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaUserList) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaUserList)null); var followersResponse = JsonConvert.DeserializeObject(json); if (!followersResponse.IsOK()) - Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUserList) null); + Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUserList)null); followers.AddRange( followersResponse.Items.Select(ConvertersFabric.GetUserConverter) .Select(converter => converter.Convert())); @@ -571,7 +572,7 @@ public async Task> GetUserFollowersAsync(string username, } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaUserList) null); + return Result.Fail(exception.Message, (InstaUserList)null); } } @@ -590,13 +591,13 @@ public async Task> GetUserTagsAsync(string username, int if (maxPages == 0) maxPages = int.MaxValue; var user = await GetUserAsync(username); if (!user.Succeeded || string.IsNullOrEmpty(user.Value.Pk)) - return Result.Fail($"Unable to get user {username}", (InstaMediaList) null); + return Result.Fail($"Unable to get user {username}", (InstaMediaList)null); var uri = UriCreator.GetUserTagsUri(user.Value?.Pk, _user.RankToken); var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, uri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); var userTags = new InstaMediaList(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaMediaList) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaMediaList)null); var mediaResponse = JsonConvert.DeserializeObject(json, new InstaMediaListDataConverter()); var nextId = mediaResponse.NextMaxId; @@ -620,7 +621,7 @@ public async Task> GetUserTagsAsync(string username, int } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaMediaList) null); + return Result.Fail(exception.Message, (InstaMediaList)null); } } @@ -635,7 +636,7 @@ public async Task> GetDirectInboxAsync() var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, directInboxUri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaDirectInboxContainer) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaDirectInboxContainer)null); var inboxResponse = JsonConvert.DeserializeObject(json); var converter = ConvertersFabric.GetDirectInboxConverter(inboxResponse); return Result.Success(converter.Convert()); @@ -656,7 +657,7 @@ public async Task> GetDirectInboxThreadAsync(str var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, directInboxUri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaDirectInboxThread) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaDirectInboxThread)null); var threadResponse = JsonConvert.DeserializeObject(json, new InstaThreadDataConverter()); var converter = ConvertersFabric.GetDirectThreadConverter(threadResponse); @@ -685,7 +686,7 @@ public async Task> GetRecentRecipientsAsync() var converter = ConvertersFabric.GetRecipientsConverter(responseRecipients); return Result.Success(converter.Convert()); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecipients) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecipients)null); } public async Task> GetRankedRecipientsAsync() @@ -703,7 +704,7 @@ public async Task> GetRankedRecipientsAsync() var converter = ConvertersFabric.GetRecipientsConverter(responseRecipients); return Result.Success(converter.Convert()); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecipients) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecipients)null); } public async Task> GetRecentActivityAsync(int maxPages = 0) @@ -781,7 +782,7 @@ public async Task> GetMediaCommentsAsync(string mediaI var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); if (response.StatusCode != HttpStatusCode.OK) - return Result.Fail($"Unexpected response status: {response.StatusCode}", (InstaCommentList) null); + return Result.Fail($"Unexpected response status: {response.StatusCode}", (InstaCommentList)null); var commentListResponse = JsonConvert.DeserializeObject(json); var converter = ConvertersFabric.GetCommentListConverter(commentListResponse); var instaComments = converter.Convert(); @@ -818,7 +819,7 @@ public async Task> GetMediaLikersAsync(string mediaId) var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, likersUri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaUserList) null); + if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaUserList)null); var instaUsers = new InstaUserList(); var mediaLikersResponse = JsonConvert.DeserializeObject(json); if (mediaLikersResponse.UsersCount < 1) return Result.Success(instaUsers); @@ -877,11 +878,11 @@ public async Task> SetAccountPrivateAsync() return Result.Success(converter.Convert()); } var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaUser) null); + return Result.Fail(status.Message, (InstaUser)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaUser) null); + return Result.Fail(exception.Message, (InstaUser)null); } } @@ -918,11 +919,11 @@ public async Task> SetAccountPublicAsync() return Result.Success(converter.Convert()); } var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaUser) null); + return Result.Fail(status.Message, (InstaUser)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaUser) null); + return Result.Fail(exception.Message, (InstaUser)null); } } @@ -957,11 +958,11 @@ public async Task> CommentMediaAsync(string mediaId, strin return Result.Success(converter.Convert()); } var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaComment) null); + return Result.Fail(status.Message, (InstaComment)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaComment) null); + return Result.Fail(exception.Message, (InstaComment)null); } } @@ -1021,11 +1022,11 @@ public async Task> UploadPhotoAsync(MediaImage image, string if (response.IsSuccessStatusCode) return await ConfigurePhotoAsync(image, uploadId, caption); var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaMedia) null); + return Result.Fail(status.Message, (InstaMedia)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaMedia) null); + return Result.Fail(exception.Message, (InstaMedia)null); } } @@ -1039,7 +1040,7 @@ public async Task> ConfigurePhotoAsync(MediaImage image, str var androidVersion = AndroidVersion.FromString(_deviceInfo.FirmwareFingerprint.Split('/')[2].Split(':')[1]); if (androidVersion == null) - return Result.Fail("Unsupported android version", (InstaMedia) null); + return Result.Fail("Unsupported android version", (InstaMedia)null); var data = new JObject { {"_uuid", _deviceInfo.DeviceGuid.ToString()}, @@ -1084,11 +1085,11 @@ public async Task> ConfigurePhotoAsync(MediaImage image, str return Result.Success(converter.Convert()); } var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaMedia) null); + return Result.Fail(status.Message, (InstaMedia)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaMedia) null); + return Result.Fail(exception.Message, (InstaMedia)null); } } @@ -1387,7 +1388,7 @@ private async Task> GetUserFeedWithMaxIdAsync(string Uri instaUri; if (!Uri.TryCreate(new Uri(InstaApiConstants.INSTAGRAM_URL), InstaApiConstants.TIMELINEFEED, out instaUri)) throw new Exception("Cant create search user URI"); - var userUriBuilder = new UriBuilder(instaUri) {Query = $"max_id={maxId}"}; + var userUriBuilder = new UriBuilder(instaUri) { Query = $"max_id={maxId}" }; var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, userUriBuilder.Uri, _deviceInfo); request.Properties.Add(new KeyValuePair(InstaApiConstants.HEADER_PHONE_ID, _requestMessage.phone_id)); @@ -1401,7 +1402,7 @@ private async Task> GetUserFeedWithMaxIdAsync(string new InstaFeedResponseDataConverter()); return Result.Success(feedResponse); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeedResponse) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFeedResponse)null); } private async Task> GetFollowingActivityWithMaxIdAsync(string maxId) @@ -1416,7 +1417,7 @@ private async Task> GetFollowingActivityWit new InstaRecentActivityConverter()); return Result.Success(followingActivity); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecentActivityResponse) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaRecentActivityResponse)null); } private async Task> GetUserMediaListWithMaxIdAsync(Uri instaUri) @@ -1430,7 +1431,7 @@ private async Task> GetUserMediaListWithMaxIdAsy new InstaMediaListDataConverter()); return Result.Success(mediaResponse); } - return Result.Fail("", (InstaMediaListResponse) null); + return Result.Fail("", (InstaMediaListResponse)null); } private async Task> GetUserFollowersWithMaxIdAsync(string username, @@ -1448,14 +1449,14 @@ private async Task> GetUserFollowersWithMaxIdAsy if (response.StatusCode == HttpStatusCode.OK) { var followersResponse = JsonConvert.DeserializeObject(json); - if (!followersResponse.IsOK()) Result.Fail("", (InstaFollowersResponse) null); + if (!followersResponse.IsOK()) Result.Fail("", (InstaFollowersResponse)null); return Result.Success(followersResponse); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFollowersResponse) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFollowersResponse)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaFollowersResponse) null); + return Result.Fail(exception.Message, (InstaFollowersResponse)null); } } @@ -1469,7 +1470,7 @@ private async Task> GetRecentActivityInternalAsync(Ur var activityFeed = new InstaActivityFeed(); var json = await response.Content.ReadAsStringAsync(); if (response.StatusCode != HttpStatusCode.OK) - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaActivityFeed) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaActivityFeed)null); var feedPage = JsonConvert.DeserializeObject(json, new InstaRecentActivityConverter()); activityFeed.IsOwnActivity = feedPage.IsOwnActivity; @@ -1500,7 +1501,7 @@ private async Task> GetTagFeedWithMaxIdAsync(str try { var instaUri = UriCreator.GetTagFeedUri(tag); - instaUri = new UriBuilder(instaUri) {Query = $"max_id={nextId}"}.Uri; + instaUri = new UriBuilder(instaUri) { Query = $"max_id={nextId}" }.Uri; var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, instaUri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); @@ -1510,11 +1511,11 @@ private async Task> GetTagFeedWithMaxIdAsync(str new InstaMediaListDataConverter()); return Result.Success(feedResponse); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMediaListResponse) null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMediaListResponse)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaMediaListResponse) null); + return Result.Fail(exception.Message, (InstaMediaListResponse)null); } } @@ -1522,7 +1523,7 @@ private async Task> GetCommentListWithMaxIdAsy string nextId) { var commentsUri = UriCreator.GetMediaCommentsUri(mediaId); - var commentsUriMaxId = new UriBuilder(commentsUri) {Query = $"max_id={nextId}"}.Uri; + var commentsUriMaxId = new UriBuilder(commentsUri) { Query = $"max_id={nextId}" }.Uri; var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, commentsUriMaxId, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); @@ -1531,7 +1532,7 @@ private async Task> GetCommentListWithMaxIdAsy var comments = JsonConvert.DeserializeObject(json); return Result.Success(comments); } - return Result.Fail("", (InstaCommentListResponse) null); + return Result.Fail("", (InstaCommentListResponse)null); } private async Task> FollowUnfollowUserInternal(long userId, Uri instaUri) @@ -1559,11 +1560,11 @@ private async Task> FollowUnfollowUserInternal(lo return Result.Success(converter.Convert()); } var status = GetBadStatusFromJsonString(json); - return Result.Fail(status.Message, (InstaFriendshipStatus) null); + return Result.Fail(status.Message, (InstaFriendshipStatus)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaFriendshipStatus) null); + return Result.Fail(exception.Message, (InstaFriendshipStatus)null); } } #endregion diff --git a/InstaSharper/Classes/ResponseType.cs b/InstaSharper/Classes/ResponseType.cs index 5032efcc..b194d746 100644 --- a/InstaSharper/Classes/ResponseType.cs +++ b/InstaSharper/Classes/ResponseType.cs @@ -5,6 +5,7 @@ public enum ResponseType Unknown = 0, LoginRequired = 1, CheckPointRequired = 2, - RequestsLimit = 3 + RequestsLimit = 3, + SentryBlock = 4 } } \ No newline at end of file diff --git a/InstaSharper/Classes/Result.cs b/InstaSharper/Classes/Result.cs index be178deb..09a20498 100644 --- a/InstaSharper/Classes/Result.cs +++ b/InstaSharper/Classes/Result.cs @@ -46,6 +46,6 @@ public static IResult Fail(string errMsg, T resValue) => new Result(false, resValue, new ResultInfo(errMsg)); public static IResult Fail(string errMsg, ResponseType responseType, T resValue) - => new Result(false, resValue, new ResultInfo(responseType)); + => new Result(false, resValue, new ResultInfo(responseType, errMsg)); } } \ No newline at end of file diff --git a/InstaSharper/Classes/ResultInfo.cs b/InstaSharper/Classes/ResultInfo.cs index 7cb8b268..88627acd 100644 --- a/InstaSharper/Classes/ResultInfo.cs +++ b/InstaSharper/Classes/ResultInfo.cs @@ -14,9 +14,10 @@ public ResultInfo(Exception exception) Exception = exception; } - public ResultInfo(ResponseType responseType) + public ResultInfo(ResponseType responseType, string errorMessage) { ResponseType = responseType; + Message = errorMessage; } public Exception Exception { get; } diff --git a/InstaSharper/Helpers/InstaProxy.cs b/InstaSharper/Helpers/InstaProxy.cs new file mode 100644 index 00000000..5dbd5c8e --- /dev/null +++ b/InstaSharper/Helpers/InstaProxy.cs @@ -0,0 +1,29 @@ +using System; +using System.Net; + +namespace InstaSharper.Helpers +{ + public class InstaProxy : IWebProxy + { + private readonly string ipaddress; + private readonly string port; + + public InstaProxy(string ipaddress, string port) + { + this.ipaddress = ipaddress; + this.port = port; + } + + public Uri GetProxy(Uri destination) + { + return new Uri($"http://{ipaddress}:{port}"); + } + + public bool IsBypassed(Uri host) + { + return false; + } + + public ICredentials Credentials { get; set; } + } +} From 0a75e24fde6db2176c4d413a7274442266e69e87 Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Thu, 8 Jun 2017 18:19:13 +0300 Subject: [PATCH 12/17] Tests corrected, removed sync methods --- .../Classes/AuthenticatedTestFixture.cs | 40 +++ .../RunnableInDebugOnlyFact.cs | 0 .../RunnableInDebugOnlyTheory.cs | 0 InstaSharper.Tests/Classes/SkippableFact.cs | 12 + InstaSharper.Tests/Endpoints/AuthTest.cs | 3 + InstaSharper.Tests/Endpoints/DiscoverTest.cs | 29 +- InstaSharper.Tests/Endpoints/FeedTest.cs | 127 ++------ InstaSharper.Tests/Endpoints/FollowersTest.cs | 52 +--- InstaSharper.Tests/Endpoints/LikesTest.cs | 29 +- InstaSharper.Tests/Endpoints/MediaTest.cs | 145 ++------- InstaSharper.Tests/Endpoints/MessagingTest.cs | 82 +---- InstaSharper.Tests/Endpoints/StoryTest.cs | 60 +--- InstaSharper.Tests/Endpoints/UploadTest.cs | 2 +- InstaSharper.Tests/Endpoints/UserInfoTest.cs | 84 ++---- InstaSharper.Tests/Utils/TestHelpers.cs | 12 +- InstaSharper/API/Builder/IInstaApiBuilder.cs | 2 + InstaSharper/API/Builder/InstaApiBuilder.cs | 10 +- InstaSharper/API/IInstaApi.cs | 280 ------------------ InstaSharper/API/InstaApi.cs | 191 +----------- .../DeviceInfo/AndroidDeviceGenerator.cs | 66 +++-- .../Android/DeviceInfo/ApiRequestMessage.cs | 22 +- .../Classes/Android/LoginInfoAndroid.cs | 6 - 22 files changed, 279 insertions(+), 975 deletions(-) create mode 100644 InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs rename InstaSharper.Tests/{Utils => Classes}/RunnableInDebugOnlyFact.cs (100%) rename InstaSharper.Tests/{Utils => Classes}/RunnableInDebugOnlyTheory.cs (100%) create mode 100644 InstaSharper.Tests/Classes/SkippableFact.cs delete mode 100644 InstaSharper/Classes/Android/LoginInfoAndroid.cs diff --git a/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs b/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs new file mode 100644 index 00000000..50ecec18 --- /dev/null +++ b/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using InstaSharper.API; +using InstaSharper.Classes; +using InstaSharper.Tests.Utils; + +namespace InstaSharper.Tests.Classes +{ + public class AuthenticatedTestFixture : IDisposable + { + private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); + private readonly string _username = "alex_codegarage"; + + public IInstaApi ApiInstance { get; } + + public AuthenticatedTestFixture() + { + ApiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData + { + UserName = _username, + Password = _password + }); + + var loginTask = Task.Run(ApiInstance.LoginAsync); + if (!loginTask.Wait(TimeSpan.FromSeconds(10))) + throw new Exception($"Unable to login, user: {_username}, password: {_password}."); + } + + public void Dispose() + { + var logoutTask = Task.Run(ApiInstance.LogoutAsync); + if (!logoutTask.Wait(TimeSpan.FromSeconds(10))) + throw new Exception($"Not able to logout, user: {_username}, password: {_password}."); + } + + public string GetUsername() => _username; + + public string GetPassword() => _password; + } +} diff --git a/InstaSharper.Tests/Utils/RunnableInDebugOnlyFact.cs b/InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs similarity index 100% rename from InstaSharper.Tests/Utils/RunnableInDebugOnlyFact.cs rename to InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs diff --git a/InstaSharper.Tests/Utils/RunnableInDebugOnlyTheory.cs b/InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs similarity index 100% rename from InstaSharper.Tests/Utils/RunnableInDebugOnlyTheory.cs rename to InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs diff --git a/InstaSharper.Tests/Classes/SkippableFact.cs b/InstaSharper.Tests/Classes/SkippableFact.cs new file mode 100644 index 00000000..85a4c467 --- /dev/null +++ b/InstaSharper.Tests/Classes/SkippableFact.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace InstaSharper.Tests.Classes +{ + public sealed class SkippableFact : FactAttribute + { + public SkippableFact() + { + Skip = "This fact marked as skippable."; + } + } +} diff --git a/InstaSharper.Tests/Endpoints/AuthTest.cs b/InstaSharper.Tests/Endpoints/AuthTest.cs index 19b06db9..fce11c38 100644 --- a/InstaSharper.Tests/Endpoints/AuthTest.cs +++ b/InstaSharper.Tests/Endpoints/AuthTest.cs @@ -21,6 +21,7 @@ public async void UserLoginFailTest() { var username = "alex_codegarage"; var password = "boombaby!"; + var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData { @@ -28,6 +29,7 @@ public async void UserLoginFailTest() Password = password }); _output.WriteLine("Got API instance"); + var loginResult = await apiInstance.LoginAsync(); Assert.False(loginResult.Succeeded); Assert.False(apiInstance.IsUserAuthenticated); @@ -44,6 +46,7 @@ public async void UserLoginSuccessTest() UserName = username, Password = password }); + Assert.False(apiInstance.IsUserAuthenticated); var loginResult = await apiInstance.LoginAsync(); Assert.True(loginResult.Succeeded); diff --git a/InstaSharper.Tests/Endpoints/DiscoverTest.cs b/InstaSharper.Tests/Endpoints/DiscoverTest.cs index 1db07aa6..686bf2e5 100644 --- a/InstaSharper.Tests/Endpoints/DiscoverTest.cs +++ b/InstaSharper.Tests/Endpoints/DiscoverTest.cs @@ -1,41 +1,30 @@ -using System; -using InstaSharper.Classes; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class DiscoverTest + public class DiscoverTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - private readonly string _username = "alex_codegarage"; + readonly AuthenticatedTestFixture _authInfo; - public DiscoverTest(ITestOutputHelper output) + public DiscoverTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyFact] public async void ExploreTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = TestHelpers.Login(apiInstance, _output); - Assert.True(loginSucceed); - var result = await apiInstance.GetExploreFeedAsync(0); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetExploreFeedAsync(2); var exploreGeed = result.Value; //assert Assert.True(result.Succeeded); Assert.NotNull(exploreGeed); } + + } } \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/FeedTest.cs b/InstaSharper.Tests/Endpoints/FeedTest.cs index a4bbd0da..92c8f8d9 100644 --- a/InstaSharper.Tests/Endpoints/FeedTest.cs +++ b/InstaSharper.Tests/Endpoints/FeedTest.cs @@ -1,47 +1,27 @@ -using System; -using System.Linq; -using InstaSharper.Classes; +using System.Linq; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class FeedTest + public class FeedTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - private readonly string _username = "alex_codegarage"; + readonly AuthenticatedTestFixture _authInfo; - public FeedTest(ITestOutputHelper output) + public FeedTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyTheory] [InlineData("christmas")] public async void GetTagFeedTest(string tag) { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - Assert.True(loginSucceed.Succeeded); - var result = await apiInstance.GetTagFeedAsync(tag, 10); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var result = await _authInfo.ApiInstance.GetTagFeedAsync(tag, 10); var tagFeed = result.Value; var anyMediaDuplicate = tagFeed.Medias.GroupBy(x => x.Code).Any(g => g.Count() > 1); var anyStoryDuplicate = tagFeed.Stories.GroupBy(x => x.Id).Any(g => g.Count() > 1); @@ -57,25 +37,9 @@ public async void GetTagFeedTest(string tag) [InlineData("rock")] public async void GetUserTagFeedTest(string username) { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - Assert.True(loginSucceed.Succeeded); - var result = await apiInstance.GetUserTagsAsync(username, 5); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var result = await _authInfo.ApiInstance.GetUserTagsAsync(username, 5); var tagFeed = result.Value; var anyMediaDuplicate = tagFeed.GroupBy(x => x.Code).Any(g => g.Count() > 1); //assert @@ -87,26 +51,9 @@ public async void GetUserTagFeedTest(string username) [RunnableInDebugOnlyFact] public async void GetFollowingRecentActivityFeedTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - //no need to perform test if account marked as unsafe - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - Assert.True(loginSucceed.Succeeded); - var getFeedResult = await apiInstance.GetFollowingRecentActivityAsync(5); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var getFeedResult = await _authInfo.ApiInstance.GetFollowingRecentActivityAsync(5); var folloowingRecentFeed = getFeedResult.Value; //assert @@ -118,25 +65,9 @@ public async void GetFollowingRecentActivityFeedTest() [RunnableInDebugOnlyFact] public async void GetRecentActivityFeedTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - Assert.True(loginSucceed.Succeeded); - var getFeedResult = await apiInstance.GetRecentActivityAsync(5); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var getFeedResult = await _authInfo.ApiInstance.GetRecentActivityAsync(5); var ownRecentFeed = getFeedResult.Value; //assert Assert.True(getFeedResult.Succeeded); @@ -147,25 +78,9 @@ public async void GetRecentActivityFeedTest() [RunnableInDebugOnlyFact] public async void GetUserFeedTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - Assert.True(loginSucceed.Succeeded); - var getFeedResult = await apiInstance.GetUserTimelineFeedAsync(5); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var getFeedResult = await _authInfo.ApiInstance.GetUserTimelineFeedAsync(5); var feed = getFeedResult.Value; var anyDuplicate = feed.Medias.GroupBy(x => x.Code).Any(g => g.Count() > 1); var anyStoryDuplicate = feed.Stories.GroupBy(x => x.Id).Any(g => g.Count() > 1); diff --git a/InstaSharper.Tests/Endpoints/FollowersTest.cs b/InstaSharper.Tests/Endpoints/FollowersTest.cs index f1201f79..0f3e85c7 100644 --- a/InstaSharper.Tests/Endpoints/FollowersTest.cs +++ b/InstaSharper.Tests/Endpoints/FollowersTest.cs @@ -1,35 +1,27 @@ -using System; -using System.Linq; -using InstaSharper.Classes; +using System.Linq; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class FollowersTest + public class FollowersTest : IClassFixture { - private readonly ITestOutputHelper _output; + readonly AuthenticatedTestFixture _authInfo; - public FollowersTest(ITestOutputHelper output) + public FollowersTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyTheory] [InlineData("therock")] public async void GetUserFollowersTest(string username) { - var currentUsername = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = currentUsername, - Password = password - }); - if (!TestHelpers.Login(apiInstance, _output)) return; - var result = await apiInstance.GetUserFollowersAsync(username, 10); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var result = await _authInfo.ApiInstance.GetUserFollowersAsync(username, 10); var followers = result.Value; var anyDuplicate = followers.GroupBy(x => x.Pk).Any(g => g.Count() > 1); @@ -42,15 +34,9 @@ public async void GetUserFollowersTest(string username) [RunnableInDebugOnlyFact] public async void GetCurrentUserFollwersTest() { - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - if (!TestHelpers.Login(apiInstance, _output)) return; - var result = await apiInstance.GetCurrentUserFollowersAsync(); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var result = await _authInfo.ApiInstance.GetCurrentUserFollowersAsync(); var followers = result.Value; //assert Assert.True(result.Succeeded); @@ -61,16 +47,10 @@ public async void GetCurrentUserFollwersTest() [InlineData(196754384)] public async void FollowUnfollowUserTest(long userId) { - var currentUsername = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = currentUsername, - Password = password - }); - if (!TestHelpers.Login(apiInstance, _output)) throw new Exception("Not logged in"); - var followResult = await apiInstance.FollowUserAsync(userId); - var unFollowResult = await apiInstance.UnFollowUserAsync(userId); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var followResult = await _authInfo.ApiInstance.FollowUserAsync(userId); + var unFollowResult = await _authInfo.ApiInstance.UnFollowUserAsync(userId); //assert Assert.True(followResult.Succeeded); Assert.True(unFollowResult.Succeeded); diff --git a/InstaSharper.Tests/Endpoints/LikesTest.cs b/InstaSharper.Tests/Endpoints/LikesTest.cs index 8dc02223..0574ae74 100644 --- a/InstaSharper.Tests/Endpoints/LikesTest.cs +++ b/InstaSharper.Tests/Endpoints/LikesTest.cs @@ -1,38 +1,27 @@ -using System; -using InstaSharper.Classes; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class LikesTest + public class LikesTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - private readonly string _username = "alex_codegarage"; + readonly AuthenticatedTestFixture _authInfo; - public LikesTest(ITestOutputHelper output) + public LikesTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyTheory] [InlineData("1484832969772514291_196754384")] public async void LikeUnlikeTest(string mediaId) { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - if (!TestHelpers.Login(apiInstance, _output)) throw new Exception("Not logged in"); - //act - var likeResult = await apiInstance.LikeMediaAsync(mediaId); - var unLikeResult = await apiInstance.UnLikeMediaAsync(mediaId); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var likeResult = await _authInfo.ApiInstance.LikeMediaAsync(mediaId); + var unLikeResult = await _authInfo.ApiInstance.UnLikeMediaAsync(mediaId); //assert Assert.True(likeResult.Succeeded); Assert.True(unLikeResult.Succeeded); diff --git a/InstaSharper.Tests/Endpoints/MediaTest.cs b/InstaSharper.Tests/Endpoints/MediaTest.cs index de852a43..73d7857f 100644 --- a/InstaSharper.Tests/Endpoints/MediaTest.cs +++ b/InstaSharper.Tests/Endpoints/MediaTest.cs @@ -1,41 +1,28 @@ using System; using System.Linq; -using InstaSharper.Classes; +using InstaSharper.Classes.Models; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; -using InstaSharper.Classes.Models; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class MediaTest + public class MediaTest : IClassFixture { - private readonly ITestOutputHelper _output; + readonly AuthenticatedTestFixture _authInfo; - public MediaTest(ITestOutputHelper output) + public MediaTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyTheory] [InlineData("1484832969772514291")] public async void GetMediaByIdTest(string mediaId) { - //arrange - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - _output.WriteLine($"Trying to login as user: {username}"); - if (!TestHelpers.Login(apiInstance, _output)) return; - _output.WriteLine($"Getting media by ID: {mediaId}"); - var media = await apiInstance.GetMediaByIdAsync(mediaId); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var media = await _authInfo.ApiInstance.GetMediaByIdAsync(mediaId); Assert.NotNull(media); } @@ -43,21 +30,9 @@ public async void GetMediaByIdTest(string mediaId) [InlineData("1379932752706850783")] public async void GetMediaLikersTest(string mediaId) { - //arrange - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - _output.WriteLine($"Trying to login as user: {username}"); - if (!TestHelpers.Login(apiInstance, _output)) return; - _output.WriteLine($"Getting media [{mediaId}] likers"); - var likers = await apiInstance.GetMediaLikersAsync(mediaId); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var likers = await _authInfo.ApiInstance.GetMediaLikersAsync(mediaId); var anyDuplicate = likers.Value.GroupBy(x => x.Pk).Any(g => g.Count() > 1); - //assert Assert.NotNull(likers); Assert.False(anyDuplicate); } @@ -66,21 +41,11 @@ public async void GetMediaLikersTest(string mediaId) [InlineData("1379932752706850783")] public async void GetMediaCommentsTest(string mediaId) { - //arrange - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - _output.WriteLine($"Trying to login as user: {username}"); - if (!TestHelpers.Login(apiInstance, _output)) return; - _output.WriteLine($"Getting media [{mediaId}] comments"); - var comments = await apiInstance.GetMediaCommentsAsync(mediaId, 0); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var comments = await _authInfo.ApiInstance.GetMediaCommentsAsync(mediaId, 3); + var anyDuplicate = comments.Value.Comments.GroupBy(x => x.Pk).Any(g => g.Count() > 1); - //assert + Assert.NotNull(comments); Assert.False(anyDuplicate); } @@ -89,25 +54,12 @@ public async void GetMediaCommentsTest(string mediaId) [InlineData("alex_codegarage")] public async void GetUserMediaListTest(string userToFetch) { - //arrange - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - var random = new Random(DateTime.Today.Millisecond); - var pages = 5; - //act - _output.WriteLine($"Trying to login as user: {username}"); - if (!TestHelpers.Login(apiInstance, _output)) return; - _output.WriteLine($"Getting posts of user: {userToFetch}"); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var random = new Random(DateTime.Now.Millisecond); - var posts = await apiInstance.GetUserMediaAsync(userToFetch, pages); + var posts = await _authInfo.ApiInstance.GetUserMediaAsync(userToFetch, 3); var anyDuplicate = posts.Value.GroupBy(x => x.Code).Any(g => g.Count() > 1); - //assert Assert.NotNull(posts); Assert.Equal(userToFetch, posts.Value[random.Next(0, posts.Value.Count)].User.UserName); Assert.False(anyDuplicate); @@ -117,21 +69,10 @@ public async void GetUserMediaListTest(string userToFetch) [InlineData("1484832969772514291_196754384")] public async void PostDeleteCommentTest(string mediaId) { - //arrange - var username = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - var text = "test comment"; - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - - var postResult = await apiInstance.CommentMediaAsync(mediaId, text); - var delResult = await apiInstance.DeleteCommentAsync(mediaId, postResult.Value.Pk); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var text = "Test comment"; + var postResult = await _authInfo.ApiInstance.CommentMediaAsync(mediaId, text); + var delResult = await _authInfo.ApiInstance.DeleteCommentAsync(mediaId, postResult.Value.Pk); Assert.True(postResult.Succeeded); Assert.Equal(text, postResult.Value.Text); Assert.True(delResult.Succeeded); @@ -141,37 +82,17 @@ public async void PostDeleteCommentTest(string mediaId) [InlineData("1510405963000000025_1414585238", InstaMediaType.Image)] public async void DeleteMediaPhotoTest(string mediaId, InstaMediaType mediaType) { - //arrange - var username = "thisidlin"; - var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var deleteMediaPhoto = await apiInstance.DeleteMediaAsync(mediaId, mediaType); - //assert - Assert.False(deleteMediaPhoto.Value); //As the media doesn't exists + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var deleteMediaPhoto = await _authInfo.ApiInstance.DeleteMediaAsync(mediaId, mediaType); + Assert.False(deleteMediaPhoto.Value); } [Theory] [InlineData("1510414591769980888_1414585238", InstaMediaType.Video)] public async void DeleteMediaVideoTest(string mediaId, InstaMediaType mediaType) { - //arrange - var username = "thisidlin"; - var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var deleteMediaVideo = await apiInstance.DeleteMediaAsync(mediaId, mediaType); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var deleteMediaVideo = await _authInfo.ApiInstance.DeleteMediaAsync(mediaId, mediaType); Assert.True(deleteMediaVideo.Value); } @@ -179,18 +100,8 @@ public async void DeleteMediaVideoTest(string mediaId, InstaMediaType mediaType) [InlineData("1513736003209429255_1414585238", "Hello!")] public async void EditMediaTest(string mediaId, string caption) { - //arrange - var username = "thisidlin"; - var password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = username, - Password = password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var editMedia = await apiInstance.EditMediaAsync(mediaId, caption); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var editMedia = await _authInfo.ApiInstance.EditMediaAsync(mediaId, caption); Assert.True(editMedia.Value); } } diff --git a/InstaSharper.Tests/Endpoints/MessagingTest.cs b/InstaSharper.Tests/Endpoints/MessagingTest.cs index d8155395..7391e740 100644 --- a/InstaSharper.Tests/Endpoints/MessagingTest.cs +++ b/InstaSharper.Tests/Endpoints/MessagingTest.cs @@ -1,39 +1,26 @@ -using System; -using InstaSharper.Classes; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class MessagingTest + public class MessagingTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - private readonly string _username = "alex_codegarage"; + readonly AuthenticatedTestFixture _authInfo; - public MessagingTest(ITestOutputHelper output) + public MessagingTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyTheory] [InlineData("340282366841710300949128137443944319108")] public async void GetDirectInboxThreadByIdTest(string threadId) { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var result = await apiInstance.GetDirectInboxThreadAsync(threadId); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetDirectInboxThreadAsync(threadId); var thread = result.Value; - //assert Assert.True(result.Succeeded); Assert.NotNull(thread); } @@ -41,18 +28,9 @@ public async void GetDirectInboxThreadByIdTest(string threadId) [RunnableInDebugOnlyFact] public async void GetDirectInboxTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var result = await apiInstance.GetDirectInboxAsync(); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetDirectInboxAsync(); var inbox = result.Value; - //assert Assert.True(result.Succeeded); Assert.NotNull(inbox); } @@ -60,50 +38,16 @@ public async void GetDirectInboxTest() [RunnableInDebugOnlyFact] public async void GetRankedeRecipientsTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - var result = await apiInstance.GetRankedRecipientsAsync(); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetRankedRecipientsAsync(); Assert.True(result.Succeeded); } [RunnableInDebugOnlyFact] public async void GetRecentRecipientsTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = await apiInstance.LoginAsync(); - //no need to perform test if account marked as unsafe - if (loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.LoginRequired - || loginSucceed.Info.ResponseType == ResponseType.RequestsLimit) - { - _output.WriteLine("Unable to login: limit reached or checkpoint required"); - return; - } - var result = await apiInstance.GetRecentRecipientsAsync(); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetRecentRecipientsAsync(); Assert.True(result.Succeeded); } } diff --git a/InstaSharper.Tests/Endpoints/StoryTest.cs b/InstaSharper.Tests/Endpoints/StoryTest.cs index 259d5363..9d9604c5 100644 --- a/InstaSharper.Tests/Endpoints/StoryTest.cs +++ b/InstaSharper.Tests/Endpoints/StoryTest.cs @@ -1,40 +1,27 @@ using System; -using InstaSharper.Classes; +using InstaSharper.Classes.Models; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; -using InstaSharper.Classes.Models; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class StoryTest + public class StoryTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = System.IO.File.ReadAllText(@"C:\privKey\instasharp.txt"); - private readonly string _username = "thisidlin"; + readonly AuthenticatedTestFixture _authInfo; - public StoryTest(ITestOutputHelper output) + public StoryTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyFact] private async void GetStoryTrayTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = TestHelpers.Login(apiInstance, _output); - Assert.True(loginSucceed); - var result = await apiInstance.GetStoryTrayAsync(); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetStoryTrayAsync(); var stories = result.Value; - //assert Assert.True(result.Succeeded); Assert.NotNull(stories); } @@ -43,19 +30,9 @@ private async void GetStoryTrayTest() [InlineData(1129166614)] private async void GetUserStoryTest(long userId) { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - var loginSucceed = TestHelpers.Login(apiInstance, _output); - Assert.True(loginSucceed); - var result = await apiInstance.GetUserStoryAsync(userId); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var result = await _authInfo.ApiInstance.GetUserStoryAsync(userId); var stories = result.Value; - //assert Assert.True(result.Succeeded); Assert.NotNull(stories); } @@ -63,27 +40,16 @@ private async void GetUserStoryTest(long userId) [RunnableInDebugOnlyFact] public async void UploadStoryImageTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - - //act - var loginSucceed = TestHelpers.Login(apiInstance, _output); - Assert.True(loginSucceed); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); var mediaImage = new MediaImage { Height = 1200, Width = 640, - URI = new Uri(@"C:\privKey\test.jpg", UriKind.Absolute).LocalPath + URI = new Uri(@"C:\test.jpg", UriKind.Absolute).LocalPath }; - var result = await apiInstance.UploadStoryPhotoAsync(mediaImage, "Lake"); + var result = await _authInfo.ApiInstance.UploadStoryPhotoAsync(mediaImage, "Lake"); - //assert Assert.True(result.Succeeded); Assert.NotNull(result.Value); } diff --git a/InstaSharper.Tests/Endpoints/UploadTest.cs b/InstaSharper.Tests/Endpoints/UploadTest.cs index 40712061..48396f8e 100644 --- a/InstaSharper.Tests/Endpoints/UploadTest.cs +++ b/InstaSharper.Tests/Endpoints/UploadTest.cs @@ -31,7 +31,7 @@ public async void UploadImage() Password = password }); - if (!TestHelpers.Login(apiInstance, _output)) return; + if (!await TestHelpers.Login(apiInstance, _output)) return; var mediaImage = new MediaImage { Height = 1080, diff --git a/InstaSharper.Tests/Endpoints/UserInfoTest.cs b/InstaSharper.Tests/Endpoints/UserInfoTest.cs index badf8b05..5895964b 100644 --- a/InstaSharper.Tests/Endpoints/UserInfoTest.cs +++ b/InstaSharper.Tests/Endpoints/UserInfoTest.cs @@ -1,98 +1,68 @@ -using System; -using InstaSharper.Classes; +using InstaSharper.Tests.Classes; using InstaSharper.Tests.Utils; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { [Collection("Endpoints")] - public class UserInfoTest + public class UserInfoTest : IClassFixture { - private readonly ITestOutputHelper _output; - private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - private readonly string _username = "alex_codegarage"; + private readonly AuthenticatedTestFixture _authInfo; - public UserInfoTest(ITestOutputHelper output) + public UserInfoTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } [RunnableInDebugOnlyFact] public async void GetCurrentUserTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var getUserResult = await apiInstance.GetCurrentUserAsync(); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var getUserResult = await _authInfo.ApiInstance.GetCurrentUserAsync(); var user = getUserResult.Value; - //assert + Assert.True(getUserResult.Succeeded); Assert.NotNull(user); - Assert.Equal(user.UserName, _username); + Assert.Equal(user.UserName, _authInfo.GetUsername()); } [RunnableInDebugOnlyFact] public async void GetUserTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var getUserResult = await apiInstance.GetUserAsync(_username); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var username = _authInfo.GetUsername(); + + var getUserResult = await _authInfo.ApiInstance.GetUserAsync(username); var user = getUserResult.Value; - //assert + Assert.True(getUserResult.Succeeded); Assert.NotNull(user); - Assert.Equal(user.UserName, _username); + Assert.Equal(user.UserName, username); } [RunnableInDebugOnlyFact] public async void SetAccountPrivacyTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var resultSetPrivate = await apiInstance.SetAccountPrivateAsync(); - var resultSetPublic = await apiInstance.SetAccountPublicAsync(); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var resultSetPrivate = await _authInfo.ApiInstance.SetAccountPrivateAsync(); + var resultSetPublic = await _authInfo.ApiInstance.SetAccountPublicAsync(); + Assert.True(resultSetPrivate.Succeeded); Assert.NotNull(resultSetPrivate.Value); Assert.True(resultSetPublic.Succeeded); Assert.NotNull(resultSetPrivate.Value); } - [RunnableInDebugOnlyFact] + [SkippableFact] public async void ChangePasswordTest() { - //arrange - var apiInstance = - TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = _username, - Password = _password - }); - //act - if (!TestHelpers.Login(apiInstance, _output)) return; - var resultChangePassword = await apiInstance.ChangePasswordAsync("oldPassword", "newPassword"); - //assert + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var password = _authInfo.GetPassword(); + + var resultChangePassword = await _authInfo.ApiInstance.ChangePasswordAsync(password, password); + Assert.True(resultChangePassword.Succeeded); Assert.NotNull(resultChangePassword.Value); } diff --git a/InstaSharper.Tests/Utils/TestHelpers.cs b/InstaSharper.Tests/Utils/TestHelpers.cs index ad2975e8..4831351b 100644 --- a/InstaSharper.Tests/Utils/TestHelpers.cs +++ b/InstaSharper.Tests/Utils/TestHelpers.cs @@ -1,7 +1,9 @@ using System.Net.Http; +using System.Threading.Tasks; using InstaSharper.API; using InstaSharper.API.Builder; using InstaSharper.Classes; +using InstaSharper.Classes.Android.DeviceInfo; using InstaSharper.Helpers; using Xunit.Abstractions; @@ -11,18 +13,24 @@ public class TestHelpers { public static IInstaApi GetDefaultInstaApiInstance(string username) { + var device = AndroidDeviceGenerator.GetByName(AndroidDevices.SAMSUNG_NOTE3); + var requestMessage = ApiRequestMessage.FromDevice(device); var apiInstance = new InstaApiBuilder() .SetUserName(username) .UseLogger(new TestLogger()) + .SetApiRequestMessage(requestMessage) .Build(); return apiInstance; } public static IInstaApi GetDefaultInstaApiInstance(UserSessionData user) { + var device = AndroidDeviceGenerator.GetByName(AndroidDevices.SAMSUNG_NOTE3); + var requestMessage = ApiRequestMessage.FromDevice(device); var apiInstance = new InstaApiBuilder() .SetUser(user) .UseLogger(new TestLogger()) + .SetApiRequestMessage(requestMessage) .Build(); return apiInstance; } @@ -37,9 +45,9 @@ public static IInstaApi GetProxifiedInstaApiInstance(UserSessionData user, Insta return apiInstance; } - public static bool Login(IInstaApi apiInstance, ITestOutputHelper output) + public static async Task Login(IInstaApi apiInstance, ITestOutputHelper output) { - var loginResult = apiInstance.Login(); + var loginResult = await apiInstance.LoginAsync(); if (!loginResult.Succeeded) { output.WriteLine($"Can't login: {loginResult.Info.Message}"); diff --git a/InstaSharper/API/Builder/IInstaApiBuilder.cs b/InstaSharper/API/Builder/IInstaApiBuilder.cs index 8f0b7f00..a2f067e7 100644 --- a/InstaSharper/API/Builder/IInstaApiBuilder.cs +++ b/InstaSharper/API/Builder/IInstaApiBuilder.cs @@ -1,5 +1,6 @@ using System.Net.Http; using InstaSharper.Classes; +using InstaSharper.Classes.Android.DeviceInfo; using InstaSharper.Logger; namespace InstaSharper.API.Builder @@ -12,5 +13,6 @@ public interface IInstaApiBuilder IInstaApiBuilder UseHttpClientHandler(HttpClientHandler handler); IInstaApiBuilder SetUserName(string username); IInstaApiBuilder SetUser(UserSessionData user); + IInstaApiBuilder SetApiRequestMessage(ApiRequestMessage requestMessage); } } \ No newline at end of file diff --git a/InstaSharper/API/Builder/InstaApiBuilder.cs b/InstaSharper/API/Builder/InstaApiBuilder.cs index d260db4b..5d254709 100644 --- a/InstaSharper/API/Builder/InstaApiBuilder.cs +++ b/InstaSharper/API/Builder/InstaApiBuilder.cs @@ -13,6 +13,7 @@ public class InstaApiBuilder : IInstaApiBuilder private ILogger _logger; private ApiRequestMessage _requestMessage; private UserSessionData _user; + private AndroidDevice device; public IInstaApi Build() { @@ -21,7 +22,6 @@ public IInstaApi Build() _httpClient = new HttpClient(_httpHandler); _httpClient.BaseAddress = new Uri(InstaApiConstants.INSTAGRAM_URL); } - AndroidDevice device = null; if (_requestMessage == null) { @@ -35,6 +35,12 @@ public IInstaApi Build() device_id = ApiRequestMessage.GenerateDeviceId() }; } + + if (string.IsNullOrEmpty(_requestMessage.password)) _requestMessage.password = _user?.Password; + if (string.IsNullOrEmpty(_requestMessage.username)) _requestMessage.username = _user?.UserName; + if (device == null && !string.IsNullOrEmpty(_requestMessage.device_id)) device = AndroidDeviceGenerator.GetById(_requestMessage.device_id); + if (device == null) AndroidDeviceGenerator.GetRandomAndroidDevice(); + var instaApi = new InstaApi(_user, _logger, _httpClient, _httpHandler, _requestMessage, device); return instaApi; } @@ -59,7 +65,7 @@ public IInstaApiBuilder UseHttpClientHandler(HttpClientHandler handler) public IInstaApiBuilder SetUserName(string username) { - _user = new UserSessionData {UserName = username}; + _user = new UserSessionData { UserName = username }; return this; } diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index b1c5c605..919413dd 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -15,286 +15,6 @@ public interface IInstaApi #endregion - #region Sync Members - - /// - /// Login using given credentials - /// - /// True is succeed - IResult Login(); - - /// - /// Logout from instagram - /// - /// True if completed without errors - IResult Logout(); - - /// - /// Get user timeline feed - /// - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetUserTimelineFeed(int maxPages = 0); - - /// - /// Get user explore feed - /// - /// Maximum count of pages to retrieve - /// > - IResult GetExploreFeed(int maxPages = 0); - - /// - /// Get all user media by username - /// - /// Username - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetUserMedia(string username, int maxPages = 0); - - /// - /// Get media by its id (code) - /// - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetMediaById(string mediaId); - - /// - /// Get user info by its user name - /// - /// Username - /// - /// - /// - IResult GetUser(string username); - - /// - /// Get currently logged in user info - /// - /// - /// - /// - IResult GetCurrentUser(); - - /// - /// Get tag feed by tag value - /// - /// Tag value - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetTagFeed(string tag, int maxPages = 0); - - /// - /// Get followers list by username - /// - /// Username - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetUserFollowers(string username, int maxPages = 0); - - /// - /// Get followers list for currently logged in user - /// - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetCurentUserFollowers(int maxPages = 0); - - - /// - /// Get user tags by username - /// Returns media list containing tags - /// - /// Username - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetUserTags(string username, int maxPages = 0); - - - /// - /// Get direct inbox threads for current user - /// - /// - /// - /// - IResult GetDirectInbox(); - - /// - /// Get direct inbox thread by its id - /// - /// Thread id - /// - /// - /// - IResult GetDirectInboxThread(string threadId); - - /// - /// Get recent recipients (threads and users) - /// - /// - /// - /// - IResult GetRecentRecipients(); - - /// - /// Get ranked recipients (threads and users) - /// - /// - /// - /// - IResult GetRankedRecipients(); - - /// - /// Get recent activity info - /// - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetRecentActivity(int maxPages = 0); - - /// - /// Get activity of following - /// - /// Maximum count of pages to retrieve - /// - /// - /// - IResult GetFollowingRecentActivity(int maxPages = 0); - - /// - /// Like instagram media by id - /// - /// Media Id - /// True if success - IResult LikeMedia(string mediaId); - - /// - /// Like instagram media by id - /// - /// Media Id - /// True if success - IResult UnlikeMedia(string mediaId); - - /// - /// Follow user by its by id - /// - /// User Id - /// True if success - IResult FollowUser(long userId); - - /// - /// Stop follow user by its by id - /// - /// User Id - /// True if success - IResult UnFollowUser(long userId); - - /// - /// Set current account private - /// - IResult SetAccountPrivate(); - - /// - /// Set current account public - /// - IResult SetAccountPublic(); - - /// - /// Comment media - /// - /// Media id - /// Comment text - IResult CommentMedia(string mediaId, string text); - - /// - /// Delete comment from media - /// - /// Media id - /// Comment id - IResult DeleteComment(string mediaId, string commentId); - - /// - /// Uploads photo - /// - /// Photo - /// Caption - /// - IResult UploadPhoto(MediaImage image, string caption); - - /// - /// Configures photo - /// - /// Photo - /// Upload id - /// Caption - /// - IResult ConfigurePhoto(MediaImage image, string uploadId, string caption); - - /// - /// Get user's Story Tray - /// - IResult GetStoryTray(); - - /// - /// Get the story by userId - /// - /// User Id - IResult GetUserStory(long userId); - - /// - /// Upload story photo - /// - /// Photo to upload - /// Caption - IResult UploadStoryPhoto(MediaImage image, string caption); - - /// - /// Configure story photo - /// - /// Photo to configure - /// Upload id - /// Caption - IResult ConfigureStoryPhoto(MediaImage image, string uploadId, string caption); - - /// - /// Change password - /// - /// The old password - /// The new password (shouldn't be the same old password, and should be a password you never used here) - /// Return true if the password is changed - IResult ChangePassword(string oldPassword, string newPassword); - - /// - /// Delete a media (photo or video) - /// - /// The media ID - /// The type of the media - /// Return true if the media is deleted - IResult DeleteMedia(string mediaId, InstaMediaType mediaType); - - /// - /// Edit the caption of the media (photo/video) - /// - /// The media ID - /// The new caption - /// Return true if everything is ok - IResult EditMedia(string mediaId, string caption); - - #endregion - #region Async Members /// diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index f6b3c973..6030063f 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -46,190 +46,6 @@ public InstaApi(UserSessionData user, public bool IsUserAuthenticated { get; private set; } - #region sync part - - public IResult Login() - { - return LoginAsync().Result; - } - - public IResult Logout() - { - return LogoutAsync().Result; - } - - public IResult GetMediaById(string mediaId) - { - return GetMediaByIdAsync(mediaId).Result; - } - - public IResult GetMediaByCode(string mediaCode) - { - return GetMediaByIdAsync(mediaCode).Result; - } - - public IResult GetUserTimelineFeed(int maxPages = 0) - { - return GetUserTimelineFeedAsync(maxPages).Result; - } - - public IResult GetUserMedia(string username, int maxPages = 0) - { - return GetUserMediaAsync(username, maxPages).Result; - } - - public IResult GetUser(string username) - { - return GetUserAsync(username).Result; - } - - public IResult GetCurrentUser() - { - return GetCurrentUserAsync().Result; - } - - public IResult GetUserFollowers(string username, int maxPages = 0) - { - return GetUserFollowersAsync(username, maxPages).Result; - } - - public IResult GetTagFeed(string tag, int maxPages = 0) - { - return GetTagFeedAsync(tag, maxPages).Result; - } - - public IResult GetExploreFeed(int maxPages = 0) - { - return GetExploreFeedAsync(maxPages).Result; - } - - public IResult GetUserTags(string username, int maxPages = 0) - { - return GetUserTagsAsync(username, maxPages).Result; - } - - public IResult GetCurentUserFollowers(int maxPages = 0) - { - return GetCurrentUserFollowersAsync(maxPages).Result; - } - - public IResult GetDirectInbox() - { - return GetDirectInboxAsync().Result; - } - - public IResult GetDirectInboxThread(string threadId) - { - return GetDirectInboxThreadAsync(threadId).Result; - } - - public IResult GetRecentRecipients() - { - return GetRecentRecipientsAsync().Result; - } - - public IResult GetRankedRecipients() - { - return GetRankedRecipientsAsync().Result; - } - - public IResult GetRecentActivity(int maxPages = 0) - { - return GetRecentActivityAsync(maxPages).Result; - } - - public IResult GetFollowingRecentActivity(int maxPages = 0) - { - return GetFollowingRecentActivityAsync(maxPages).Result; - } - - public IResult LikeMedia(string mediaId) - { - return LikeMediaAsync(mediaId).Result; - } - - public IResult UnlikeMedia(string mediaId) - { - return UnLikeMediaAsync(mediaId).Result; - } - - public IResult FollowUser(long userId) - { - return FollowUserAsync(userId).Result; - } - - public IResult UnFollowUser(long userId) - { - return UnFollowUserAsync(userId).Result; - } - - public IResult SetAccountPrivate() - { - return SetAccountPrivateAsync().Result; - } - - public IResult SetAccountPublic() - { - return SetAccountPublicAsync().Result; - } - - public IResult CommentMedia(string mediaId, string text) - { - return CommentMediaAsync(mediaId, text).Result; - } - - public IResult DeleteComment(string mediaId, string commentId) - { - return DeleteCommentAsync(mediaId, commentId).Result; - } - - public IResult UploadPhoto(MediaImage image, string caption) - { - return UploadPhotoAsync(image, caption).Result; - } - - public IResult ConfigurePhoto(MediaImage image, string uploadId, string caption) - { - return ConfigurePhotoAsync(image, uploadId, caption).Result; - } - - public IResult GetStoryTray() - { - return GetStoryTrayAsync().Result; - } - - public IResult GetUserStory(long userId) - { - return GetUserStoryAsync(userId).Result; - } - - public IResult UploadStoryPhoto(MediaImage image, string caption) - { - return UploadStoryPhotoAsync(image, caption).Result; - } - - public IResult ConfigureStoryPhoto(MediaImage image, string uploadId, string caption) - { - return ConfigureStoryPhotoAsync(image, uploadId, caption).Result; - } - - public IResult ChangePassword(string oldPassword, string newPassword) - { - return ChangePasswordAsync(oldPassword, newPassword).Result; - } - - public IResult DeleteMedia(string mediaId, InstaMediaType mediaType) - { - return DeleteMediaAsync(mediaId, mediaType).Result; - } - - public IResult EditMedia(string mediaId, string caption) - { - return EditMediaAsync(mediaId, caption).Result; - } - - #endregion - #region async part public async Task> LoginAsync() @@ -390,8 +206,9 @@ public async Task> GetUserMediaAsync(string username, in { ValidateUser(); if (maxPages == 0) maxPages = int.MaxValue; - var user = GetUser(username).Value; - var instaUri = UriCreator.GetUserMediaListUri(user.Pk); + var user = await GetUserAsync(username); + if (!user.Succeeded) return Result.Fail("Unable to get current user"); + var instaUri = UriCreator.GetUserMediaListUri(user.Value.Pk); var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, instaUri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); @@ -406,7 +223,7 @@ public async Task> GetUserMediaAsync(string username, in var nextId = mediaResponse.NextMaxId; while (moreAvailable && mediaList.Pages < maxPages) { - instaUri = UriCreator.GetMediaListWithMaxIdUri(user.Pk, nextId); + instaUri = UriCreator.GetMediaListWithMaxIdUri(user.Value.Pk, nextId); var nextMedia = await GetUserMediaListWithMaxIdAsync(instaUri); mediaList.Pages++; if (!nextMedia.Succeeded) diff --git a/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs b/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs index cbb50c8b..56a1ae4c 100644 --- a/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs +++ b/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; namespace InstaSharper.Classes.Android.DeviceInfo { - public class AndroidDeviceGenerator + public class AndroidDevices { public const string LG_OPTIMUS_G = "lg-optimus-g"; public const string NEXUS7_GEN2 = "nexus7gen2"; @@ -12,24 +13,27 @@ public class AndroidDeviceGenerator public const string GALAXY5 = "galaxy-s5-gold"; public const string LG_OPTIMUS_F6 = "lg-optimus-f6"; public const string GALAXY_TAB = "galaxy-tab-s84"; - public const string SAMSUNG_NOT3 = "note3"; + public const string SAMSUNG_NOTE3 = "note3"; public const string NEXUS4_CHROMA = "nexus4-chroma"; public const string SONY_Z3_COMPACT = "sony-z3-compact"; public const string XPERIA_Z5 = "xperia-z5"; + } + public class AndroidDeviceGenerator + { private static readonly List DevicesNames = new List { - LG_OPTIMUS_G, - NEXUS7_GEN2, - HTC10, - GALAXY6, - GALAXY5, - LG_OPTIMUS_F6, - GALAXY_TAB, - SAMSUNG_NOT3, - NEXUS4_CHROMA, - SONY_Z3_COMPACT, - XPERIA_Z5 + AndroidDevices.LG_OPTIMUS_G, + AndroidDevices.NEXUS7_GEN2, + AndroidDevices.HTC10, + AndroidDevices.GALAXY6, + AndroidDevices.GALAXY5, + AndroidDevices.LG_OPTIMUS_F6, + AndroidDevices.GALAXY_TAB, + AndroidDevices.SAMSUNG_NOTE3, + AndroidDevices.NEXUS4_CHROMA, + AndroidDevices.SONY_Z3_COMPACT, + AndroidDevices.XPERIA_Z5 }; public static Dictionary AndroidAndroidDeviceSets = new Dictionary @@ -323,7 +327,6 @@ public class AndroidDeviceGenerator AndroidBoardName = "hammerhead", AndroidBootloader = "HHZ20b", DeviceBrand = "google", - DeviceId = "8525f5d8201f78b5", DeviceModel = "Nexus 5", DeviceModelBoot = "qcom", DeviceModelIdentifier = "hammerhead", @@ -334,7 +337,8 @@ public class AndroidDeviceGenerator HardwareManufacturer = "LGE", HardwareModel = "Nexus 5", DeviceGuid = new Guid("dde2038c-4f1c-465a-982d-9c844fd2b80a"), - PhoneGuid = new Guid("d8d75d13-a124-4304-a935-0247ed1656cb") + PhoneGuid = new Guid("d8d75d13-a124-4304-a935-0247ed1656cb"), + DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("dde2038c-4f1c-465a-982d-9c844fd2b80a")) } }, { @@ -354,7 +358,9 @@ public class AndroidDeviceGenerator HardwareManufacturer = "samsung", HardwareModel = "SM-N915W8", DeviceGuid = new Guid("fe46d44b-e00c-4f1b-9718-7c4dae2160cc"), - PhoneGuid = new Guid("0bcbf7e0-a73f-4424-8c70-c2d38ae42d5d") + PhoneGuid = new Guid("0bcbf7e0-a73f-4424-8c70-c2d38ae42d5d"), + DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("fe46d44b-e00c-4f1b-9718-7c4dae2160cc")) + } }, { @@ -374,12 +380,14 @@ public class AndroidDeviceGenerator HardwareManufacturer = "LGE", HardwareModel = "Nexus 4", DeviceGuid = new Guid("2c4ae214-c037-486c-a335-76a1f6973445"), - PhoneGuid = new Guid("7fb2eb38-04ab-4c51-bd0c-694c7da2187e") + PhoneGuid = new Guid("7fb2eb38-04ab-4c51-bd0c-694c7da2187e"), + DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("2c4ae214-c037-486c-a335-76a1f6973445")) + } }, { - "note3", + AndroidDevices.SAMSUNG_NOTE3, new AndroidDevice { AndroidBoardName = "MSM8974", @@ -395,11 +403,13 @@ public class AndroidDeviceGenerator HardwareManufacturer = "samsung", HardwareModel = "SM-N900P", DeviceGuid = new Guid("7f585e77-becf-4137-bf1f-84ab72e35eb4"), - PhoneGuid = new Guid("28484284-e646-4a29-88fc-76c2666d5ab3") + PhoneGuid = new Guid("28484284-e646-4a29-88fc-76c2666d5ab3"), + DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("7f585e77-becf-4137-bf1f-84ab72e35eb4")) + } }, { - "galaxy-tab-s84", + AndroidDevices.GALAXY_TAB, new AndroidDevice { AndroidBoardName = "universal5420", @@ -415,17 +425,29 @@ public class AndroidDeviceGenerator HardwareManufacturer = "samsung", HardwareModel = "SM-T705", DeviceGuid = new Guid("c319490f-6f09-467b-b2a5-6f1db13348e9"), - PhoneGuid = new Guid("849a7ae1-cf94-4dd5-a977-a2f3e8363e66") + PhoneGuid = new Guid("849a7ae1-cf94-4dd5-a977-a2f3e8363e66"), + DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("c319490f-6f09-467b-b2a5-6f1db13348e9")) } } }; public static AndroidDevice GetRandomAndroidDevice() { - var random = new Random(); + var random = new Random(DateTime.Now.Millisecond); var randmonDeviceIndex = random.Next(0, DevicesNames.Count); var randomDeviceName = DevicesNames[randmonDeviceIndex]; return AndroidAndroidDeviceSets[randomDeviceName]; } + + public static AndroidDevice GetByName(string name) + { + return AndroidAndroidDeviceSets[name]; + + } + + public static AndroidDevice GetById(string deviceId) + { + return (from androidAndroidDeviceSet in AndroidAndroidDeviceSets where androidAndroidDeviceSet.Value.DeviceId == deviceId select androidAndroidDeviceSet.Value).FirstOrDefault(); + } } } \ No newline at end of file diff --git a/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs b/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs index b682d9b9..f1917b6a 100644 --- a/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs +++ b/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs @@ -35,15 +35,31 @@ internal bool IsEmpty() internal static string GenerateDeviceId() { - var hashedGuid = CryptoHelper.CalculateMd5(Guid.NewGuid().ToString()); - return $"android-{hashedGuid.Substring(0, 16)}"; + return GenerateDeviceIdFromGuid(Guid.NewGuid()); } internal static string GenerateUploadId() { var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0); - var uploadId = (long) timeSpan.TotalSeconds; + var uploadId = (long)timeSpan.TotalSeconds; return uploadId.ToString(); } + + public static ApiRequestMessage FromDevice(AndroidDevice device) + { + var requestMessage = new ApiRequestMessage() + { + phone_id = device.PhoneGuid.ToString(), + guid = device.DeviceGuid, + device_id = device.DeviceId + }; + return requestMessage; + } + + public static string GenerateDeviceIdFromGuid(Guid guid) + { + var hashedGuid = CryptoHelper.CalculateMd5(guid.ToString()); + return $"android-{hashedGuid.Substring(0, 16)}"; + } } } \ No newline at end of file diff --git a/InstaSharper/Classes/Android/LoginInfoAndroid.cs b/InstaSharper/Classes/Android/LoginInfoAndroid.cs deleted file mode 100644 index 0d02205c..00000000 --- a/InstaSharper/Classes/Android/LoginInfoAndroid.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace InstaSharper.Classes.Android -{ - public class LoginInfoAndroid - { - } -} \ No newline at end of file From 679f43518bfc1f5ac166bbd2090735f37f4a0bd1 Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Fri, 9 Jun 2017 17:54:49 +0300 Subject: [PATCH 13/17] #22, #37, #38, tests improved again, like feed added --- .../Classes/AuthenticatedTestFixture.cs | 16 +- .../Classes/RunnableInDebugOnlyFact.cs | 2 +- .../Classes/RunnableInDebugOnlyTheory.cs | 2 +- InstaSharper.Tests/Classes/SkippableFact.cs | 2 +- InstaSharper.Tests/Endpoints/AuthTest.cs | 8 +- InstaSharper.Tests/Endpoints/DiscoverTest.cs | 11 +- InstaSharper.Tests/Endpoints/FeedTest.cs | 32 +++- InstaSharper.Tests/Endpoints/FollowersTest.cs | 33 +++- InstaSharper.Tests/Endpoints/LikesTest.cs | 7 +- InstaSharper.Tests/Endpoints/MediaTest.cs | 15 +- InstaSharper.Tests/Endpoints/MessagingTest.cs | 15 +- InstaSharper.Tests/Endpoints/StoryTest.cs | 25 ++- InstaSharper.Tests/Endpoints/UploadTest.cs | 36 ++-- InstaSharper.Tests/Endpoints/UserInfoTest.cs | 37 ++-- .../Infrastructure/ApiInstanceBuilderTest.cs | 2 +- InstaSharper.Tests/Utils/TestHelpers.cs | 2 +- InstaSharper/API/Builder/InstaApiBuilder.cs | 2 +- InstaSharper/API/IInstaApi.cs | 24 ++- InstaSharper/API/InstaApi.cs | 164 +++++++++++------- InstaSharper/API/InstaApiConstants.cs | 9 +- .../DeviceInfo/AndroidDeviceGenerator.cs | 4 - .../Android/DeviceInfo/ApiRequestMessage.cs | 4 +- InstaSharper/Classes/Models/InstaCarousel.cs | 5 +- InstaSharper/Classes/Models/InstaMedia.cs | 1 - InstaSharper/Classes/Models/InstaStoryItem.cs | 25 ++- .../Classes/Models/InstaStoryMedia.cs | 8 +- InstaSharper/Classes/Models/InstaStoryTray.cs | 6 +- InstaSharper/Classes/Models/MediaVideo.cs | 2 - InstaSharper/Classes/ResponseType.cs | 3 +- .../BadStatusErrorsResponse.cs | 8 +- .../ResponseWrappers/DeleteResponse.cs | 10 +- .../Classes/ResponseWrappers/ImageResponse.cs | 2 +- .../InstaStoryItemResponse.cs | 33 ++-- .../InstaStoryMediaResponse.cs | 7 +- .../ResponseWrappers/InstaStoryResponse.cs | 3 +- .../InstaStoryTrayResponse.cs | 9 +- ...rsResponse.cs => InstaUserListResponse.cs} | 2 +- .../InstaVideoCandidatesResponse.cs | 10 +- InstaSharper/Classes/Result.cs | 29 +++- InstaSharper/Converters/ConvertersFabric.cs | 8 +- .../Converters/InstaStoryMediaConverter.cs | 7 +- .../Converters/InstaStoryTrayConverter.cs | 5 +- .../Json/InstaCommentDataConverter.cs | 4 +- .../Json/InstaFeedResponseDataConverter.cs | 4 +- .../Json/InstaFriendShipDataConverter.cs | 7 +- .../Json/InstaMediaListDataConverter.cs | 4 +- .../Json/InstaRecentActivityConverter.cs | 4 +- .../Json/InstaRecipientsDataConverter.cs | 4 +- .../Json/InstaThreadDataConverter.cs | 4 +- InstaSharper/Helpers/HttpHelper.cs | 8 +- InstaSharper/Helpers/InstaProxy.cs | 2 +- InstaSharper/Helpers/UriCreator.cs | 37 +++- 52 files changed, 402 insertions(+), 311 deletions(-) rename InstaSharper/Classes/ResponseWrappers/{InstaFollowersResponse.cs => InstaUserListResponse.cs} (91%) diff --git a/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs b/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs index 50ecec18..e4770b35 100644 --- a/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs +++ b/InstaSharper.Tests/Classes/AuthenticatedTestFixture.cs @@ -11,8 +11,6 @@ public class AuthenticatedTestFixture : IDisposable private readonly string _password = Environment.GetEnvironmentVariable("instaapiuserpassword"); private readonly string _username = "alex_codegarage"; - public IInstaApi ApiInstance { get; } - public AuthenticatedTestFixture() { ApiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData @@ -26,6 +24,8 @@ public AuthenticatedTestFixture() throw new Exception($"Unable to login, user: {_username}, password: {_password}."); } + public IInstaApi ApiInstance { get; } + public void Dispose() { var logoutTask = Task.Run(ApiInstance.LogoutAsync); @@ -33,8 +33,14 @@ public void Dispose() throw new Exception($"Not able to logout, user: {_username}, password: {_password}."); } - public string GetUsername() => _username; + public string GetUsername() + { + return _username; + } - public string GetPassword() => _password; + public string GetPassword() + { + return _password; + } } -} +} \ No newline at end of file diff --git a/InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs b/InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs index d9a216e6..0105a82a 100644 --- a/InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs +++ b/InstaSharper.Tests/Classes/RunnableInDebugOnlyFact.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using Xunit; -namespace InstaSharper.Tests.Utils +namespace InstaSharper.Tests.Classes { public sealed class RunnableInDebugOnlyFact : FactAttribute { diff --git a/InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs b/InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs index cf2d1ac6..878182e5 100644 --- a/InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs +++ b/InstaSharper.Tests/Classes/RunnableInDebugOnlyTheory.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using Xunit; -namespace InstaSharper.Tests.Utils +namespace InstaSharper.Tests.Classes { public sealed class RunnableInDebugOnlyTheory : TheoryAttribute { diff --git a/InstaSharper.Tests/Classes/SkippableFact.cs b/InstaSharper.Tests/Classes/SkippableFact.cs index 85a4c467..2e942666 100644 --- a/InstaSharper.Tests/Classes/SkippableFact.cs +++ b/InstaSharper.Tests/Classes/SkippableFact.cs @@ -9,4 +9,4 @@ public SkippableFact() Skip = "This fact marked as skippable."; } } -} +} \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/AuthTest.cs b/InstaSharper.Tests/Endpoints/AuthTest.cs index fce11c38..4d0ffae4 100644 --- a/InstaSharper.Tests/Endpoints/AuthTest.cs +++ b/InstaSharper.Tests/Endpoints/AuthTest.cs @@ -9,14 +9,14 @@ namespace InstaSharper.Tests.Endpoints [Collection("Endpoints")] public class AuthTest { - private readonly ITestOutputHelper _output; - public AuthTest(ITestOutputHelper output) { _output = output; } - [RunnableInDebugOnlyFact] + private readonly ITestOutputHelper _output; + + [Fact] public async void UserLoginFailTest() { var username = "alex_codegarage"; @@ -35,7 +35,7 @@ public async void UserLoginFailTest() Assert.False(apiInstance.IsUserAuthenticated); } - [RunnableInDebugOnlyFact] + [Fact] public async void UserLoginSuccessTest() { var username = "alex_codegarage"; diff --git a/InstaSharper.Tests/Endpoints/DiscoverTest.cs b/InstaSharper.Tests/Endpoints/DiscoverTest.cs index 686bf2e5..aad1617e 100644 --- a/InstaSharper.Tests/Endpoints/DiscoverTest.cs +++ b/InstaSharper.Tests/Endpoints/DiscoverTest.cs @@ -1,20 +1,19 @@ using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class DiscoverTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; - public DiscoverTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyFact] + private readonly AuthenticatedTestFixture _authInfo; + + [Fact] public async void ExploreTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -24,7 +23,5 @@ public async void ExploreTest() Assert.True(result.Succeeded); Assert.NotNull(exploreGeed); } - - } } \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/FeedTest.cs b/InstaSharper.Tests/Endpoints/FeedTest.cs index 92c8f8d9..0aa1ab73 100644 --- a/InstaSharper.Tests/Endpoints/FeedTest.cs +++ b/InstaSharper.Tests/Endpoints/FeedTest.cs @@ -1,21 +1,20 @@ using System.Linq; using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class FeedTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; - public FeedTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyTheory] + private readonly AuthenticatedTestFixture _authInfo; + + [Theory] [InlineData("christmas")] public async void GetTagFeedTest(string tag) { @@ -33,7 +32,7 @@ public async void GetTagFeedTest(string tag) } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("rock")] public async void GetUserTagFeedTest(string username) { @@ -48,7 +47,7 @@ public async void GetUserTagFeedTest(string username) Assert.False(anyMediaDuplicate); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetFollowingRecentActivityFeedTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -62,7 +61,7 @@ public async void GetFollowingRecentActivityFeedTest() Assert.True(!folloowingRecentFeed.IsOwnActivity); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetRecentActivityFeedTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -75,7 +74,7 @@ public async void GetRecentActivityFeedTest() Assert.True(ownRecentFeed.IsOwnActivity); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetUserFeedTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -91,5 +90,20 @@ public async void GetUserFeedTest() Assert.False(anyDuplicate); Assert.False(anyStoryDuplicate); } + + [Fact] + public async void GetUserLikeFeedTest() + { + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var getFeedResult = await _authInfo.ApiInstance.GetLikeFeedAsync(2); + var feed = getFeedResult.Value; + var anyDuplicate = feed.GroupBy(x => x.Code).Any(g => g.Count() > 1); + + //assert + Assert.True(getFeedResult.Succeeded); + Assert.NotNull(feed); + Assert.False(anyDuplicate); + } } } \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/FollowersTest.cs b/InstaSharper.Tests/Endpoints/FollowersTest.cs index 0f3e85c7..89189a82 100644 --- a/InstaSharper.Tests/Endpoints/FollowersTest.cs +++ b/InstaSharper.Tests/Endpoints/FollowersTest.cs @@ -1,21 +1,20 @@ using System.Linq; using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class FollowersTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; - public FollowersTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyTheory] + private readonly AuthenticatedTestFixture _authInfo; + + [Theory] [InlineData("therock")] public async void GetUserFollowersTest(string username) { @@ -31,19 +30,23 @@ public async void GetUserFollowersTest(string username) Assert.False(anyDuplicate); } - [RunnableInDebugOnlyFact] - public async void GetCurrentUserFollwersTest() + [Theory] + [InlineData("therock")] + public async void GetUserFollowingTest(string username) { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); - var result = await _authInfo.ApiInstance.GetCurrentUserFollowersAsync(); + var result = await _authInfo.ApiInstance.GetUserFollowingAsync(username, 10); var followers = result.Value; + var anyDuplicate = followers.GroupBy(x => x.Pk).Any(g => g.Count() > 1); + //assert Assert.True(result.Succeeded); Assert.NotNull(followers); + Assert.False(anyDuplicate); } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData(196754384)] public async void FollowUnfollowUserTest(long userId) { @@ -58,5 +61,17 @@ public async void FollowUnfollowUserTest(long userId) Assert.True(followResult.Value.Following); Assert.False(unFollowResult.Value.Following); } + + [Fact] + public async void GetCurrentUserFollwersTest() + { + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + + var result = await _authInfo.ApiInstance.GetCurrentUserFollowersAsync(); + var followers = result.Value; + //assert + Assert.True(result.Succeeded); + Assert.NotNull(followers); + } } } \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/LikesTest.cs b/InstaSharper.Tests/Endpoints/LikesTest.cs index 0574ae74..a0cf4fe3 100644 --- a/InstaSharper.Tests/Endpoints/LikesTest.cs +++ b/InstaSharper.Tests/Endpoints/LikesTest.cs @@ -1,20 +1,19 @@ using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class LikesTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; + private readonly AuthenticatedTestFixture _authInfo; public LikesTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("1484832969772514291_196754384")] public async void LikeUnlikeTest(string mediaId) { diff --git a/InstaSharper.Tests/Endpoints/MediaTest.cs b/InstaSharper.Tests/Endpoints/MediaTest.cs index 73d7857f..ab06ff21 100644 --- a/InstaSharper.Tests/Endpoints/MediaTest.cs +++ b/InstaSharper.Tests/Endpoints/MediaTest.cs @@ -2,22 +2,21 @@ using System.Linq; using InstaSharper.Classes.Models; using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class MediaTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; + private readonly AuthenticatedTestFixture _authInfo; public MediaTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("1484832969772514291")] public async void GetMediaByIdTest(string mediaId) { @@ -26,7 +25,7 @@ public async void GetMediaByIdTest(string mediaId) Assert.NotNull(media); } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("1379932752706850783")] public async void GetMediaLikersTest(string mediaId) { @@ -37,7 +36,7 @@ public async void GetMediaLikersTest(string mediaId) Assert.False(anyDuplicate); } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("1379932752706850783")] public async void GetMediaCommentsTest(string mediaId) { @@ -50,7 +49,7 @@ public async void GetMediaCommentsTest(string mediaId) Assert.False(anyDuplicate); } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("alex_codegarage")] public async void GetUserMediaListTest(string userToFetch) { @@ -65,7 +64,7 @@ public async void GetUserMediaListTest(string userToFetch) Assert.False(anyDuplicate); } - [RunnableInDebugOnlyTheory] + [Theory] [InlineData("1484832969772514291_196754384")] public async void PostDeleteCommentTest(string mediaId) { diff --git a/InstaSharper.Tests/Endpoints/MessagingTest.cs b/InstaSharper.Tests/Endpoints/MessagingTest.cs index 7391e740..3400d1ee 100644 --- a/InstaSharper.Tests/Endpoints/MessagingTest.cs +++ b/InstaSharper.Tests/Endpoints/MessagingTest.cs @@ -1,20 +1,19 @@ using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class MessagingTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; - public MessagingTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyTheory] + private readonly AuthenticatedTestFixture _authInfo; + + [Theory] [InlineData("340282366841710300949128137443944319108")] public async void GetDirectInboxThreadByIdTest(string threadId) { @@ -25,7 +24,7 @@ public async void GetDirectInboxThreadByIdTest(string threadId) Assert.NotNull(thread); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetDirectInboxTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -35,7 +34,7 @@ public async void GetDirectInboxTest() Assert.NotNull(inbox); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetRankedeRecipientsTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -43,7 +42,7 @@ public async void GetRankedeRecipientsTest() Assert.True(result.Succeeded); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetRecentRecipientsTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); diff --git a/InstaSharper.Tests/Endpoints/StoryTest.cs b/InstaSharper.Tests/Endpoints/StoryTest.cs index 9d9604c5..b78415e9 100644 --- a/InstaSharper.Tests/Endpoints/StoryTest.cs +++ b/InstaSharper.Tests/Endpoints/StoryTest.cs @@ -1,43 +1,42 @@ using System; using InstaSharper.Classes.Models; using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class StoryTest : IClassFixture { - readonly AuthenticatedTestFixture _authInfo; - public StoryTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyFact] - private async void GetStoryTrayTest() + private readonly AuthenticatedTestFixture _authInfo; + + [Theory] + [InlineData(1129166614)] + private async void GetUserStoryTest(long userId) { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); - var result = await _authInfo.ApiInstance.GetStoryTrayAsync(); + var result = await _authInfo.ApiInstance.GetUserStoryAsync(userId); var stories = result.Value; Assert.True(result.Succeeded); Assert.NotNull(stories); } - [RunnableInDebugOnlyTheory] - [InlineData(1129166614)] - private async void GetUserStoryTest(long userId) + [Fact] + private async void GetStoryTrayTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); - var result = await _authInfo.ApiInstance.GetUserStoryAsync(userId); + var result = await _authInfo.ApiInstance.GetStoryTrayAsync(); var stories = result.Value; Assert.True(result.Succeeded); Assert.NotNull(stories); } - [RunnableInDebugOnlyFact] + [Fact] public async void UploadStoryImageTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -54,4 +53,4 @@ public async void UploadStoryImageTest() Assert.NotNull(result.Value); } } -} +} \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/UploadTest.cs b/InstaSharper.Tests/Endpoints/UploadTest.cs index 48396f8e..dcc7448f 100644 --- a/InstaSharper.Tests/Endpoints/UploadTest.cs +++ b/InstaSharper.Tests/Endpoints/UploadTest.cs @@ -1,48 +1,36 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using InstaSharper.Classes; using InstaSharper.Classes.Models; -using InstaSharper.Tests.Utils; +using InstaSharper.Tests.Classes; using Xunit; -using Xunit.Abstractions; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] - public class UploadTest + [Trait("Category", "Endpoint")] + public class UploadTest : IClassFixture { - private readonly ITestOutputHelper _output; - - public UploadTest(ITestOutputHelper output) + public UploadTest(AuthenticatedTestFixture authInfo) { - _output = output; + _authInfo = authInfo; } - [RunnableInDebugOnlyFact] + private readonly AuthenticatedTestFixture _authInfo; + + [Fact] public async void UploadImage() { - var currentUsername = "alex_codegarage"; - var password = Environment.GetEnvironmentVariable("instaapiuserpassword"); - var apiInstance = TestHelpers.GetDefaultInstaApiInstance(new UserSessionData - { - UserName = currentUsername, - Password = password - }); + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); - if (!await TestHelpers.Login(apiInstance, _output)) return; var mediaImage = new MediaImage { Height = 1080, Width = 1080, URI = new Uri(@"D:\Dropbox\Public\Inspire.jpg", UriKind.Absolute).LocalPath }; - var result = await apiInstance.UploadPhotoAsync(mediaImage, "inspire"); - + var result = await _authInfo.ApiInstance.UploadPhotoAsync(mediaImage, "inspire"); + //assert Assert.True(result.Succeeded); Assert.NotNull(result.Value); } } -} +} \ No newline at end of file diff --git a/InstaSharper.Tests/Endpoints/UserInfoTest.cs b/InstaSharper.Tests/Endpoints/UserInfoTest.cs index 5895964b..bebec6a9 100644 --- a/InstaSharper.Tests/Endpoints/UserInfoTest.cs +++ b/InstaSharper.Tests/Endpoints/UserInfoTest.cs @@ -1,20 +1,31 @@ using InstaSharper.Tests.Classes; -using InstaSharper.Tests.Utils; using Xunit; namespace InstaSharper.Tests.Endpoints { - [Collection("Endpoints")] + [Trait("Category", "Endpoint")] public class UserInfoTest : IClassFixture { - private readonly AuthenticatedTestFixture _authInfo; - public UserInfoTest(AuthenticatedTestFixture authInfo) { _authInfo = authInfo; } - [RunnableInDebugOnlyFact] + private readonly AuthenticatedTestFixture _authInfo; + + [SkippableFact] + public async void ChangePasswordTest() + { + Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); + var password = _authInfo.GetPassword(); + + var resultChangePassword = await _authInfo.ApiInstance.ChangePasswordAsync(password, password); + + Assert.True(resultChangePassword.Succeeded); + Assert.NotNull(resultChangePassword.Value); + } + + [Fact] public async void GetCurrentUserTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -27,7 +38,7 @@ public async void GetCurrentUserTest() Assert.Equal(user.UserName, _authInfo.GetUsername()); } - [RunnableInDebugOnlyFact] + [Fact] public async void GetUserTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -41,7 +52,7 @@ public async void GetUserTest() Assert.Equal(user.UserName, username); } - [RunnableInDebugOnlyFact] + [Fact] public async void SetAccountPrivacyTest() { Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); @@ -54,17 +65,5 @@ public async void SetAccountPrivacyTest() Assert.True(resultSetPublic.Succeeded); Assert.NotNull(resultSetPrivate.Value); } - - [SkippableFact] - public async void ChangePasswordTest() - { - Assert.True(_authInfo.ApiInstance.IsUserAuthenticated); - var password = _authInfo.GetPassword(); - - var resultChangePassword = await _authInfo.ApiInstance.ChangePasswordAsync(password, password); - - Assert.True(resultChangePassword.Succeeded); - Assert.NotNull(resultChangePassword.Value); - } } } \ No newline at end of file diff --git a/InstaSharper.Tests/Infrastructure/ApiInstanceBuilderTest.cs b/InstaSharper.Tests/Infrastructure/ApiInstanceBuilderTest.cs index f3832b6b..b0e4fc82 100644 --- a/InstaSharper.Tests/Infrastructure/ApiInstanceBuilderTest.cs +++ b/InstaSharper.Tests/Infrastructure/ApiInstanceBuilderTest.cs @@ -4,7 +4,7 @@ namespace InstaSharper.Tests.Infrastructure { - [Collection("Infrastructure")] + [Trait("Category", "Infrastructure")] public class ApiInstanceBuilderTest { [Fact] diff --git a/InstaSharper.Tests/Utils/TestHelpers.cs b/InstaSharper.Tests/Utils/TestHelpers.cs index 4831351b..df3f1157 100644 --- a/InstaSharper.Tests/Utils/TestHelpers.cs +++ b/InstaSharper.Tests/Utils/TestHelpers.cs @@ -37,7 +37,7 @@ public static IInstaApi GetDefaultInstaApiInstance(UserSessionData user) public static IInstaApi GetProxifiedInstaApiInstance(UserSessionData user, InstaProxy proxy) { - var handler = new HttpClientHandler { Proxy = proxy }; + var handler = new HttpClientHandler {Proxy = proxy}; var apiInstance = new InstaApiBuilder() .UseHttpClientHandler(handler) .SetUser(user) diff --git a/InstaSharper/API/Builder/InstaApiBuilder.cs b/InstaSharper/API/Builder/InstaApiBuilder.cs index 5d254709..261dbab1 100644 --- a/InstaSharper/API/Builder/InstaApiBuilder.cs +++ b/InstaSharper/API/Builder/InstaApiBuilder.cs @@ -65,7 +65,7 @@ public IInstaApiBuilder UseHttpClientHandler(HttpClientHandler handler) public IInstaApiBuilder SetUserName(string username) { - _user = new UserSessionData { UserName = username }; + _user = new UserSessionData {UserName = username}; return this; } diff --git a/InstaSharper/API/IInstaApi.cs b/InstaSharper/API/IInstaApi.cs index 919413dd..26d1f7e1 100644 --- a/InstaSharper/API/IInstaApi.cs +++ b/InstaSharper/API/IInstaApi.cs @@ -101,6 +101,16 @@ public interface IInstaApi /// Task> GetUserFollowersAsync(string username, int maxPages = 0); + /// + /// Get following list by username asynchronously + /// + /// Username + /// Maximum count of pages to retrieve + /// + /// + /// + Task> GetUserFollowingAsync(string username, int maxPages = 0); + /// /// Get followers list for currently logged in user asynchronously /// @@ -279,7 +289,10 @@ public interface IInstaApi /// Change password /// /// The old password - /// The new password (shouldn't be the same old password, and should be a password you never used here) + /// + /// The new password (shouldn't be the same old password, and should be a password you never used + /// here) + /// /// Return true if the password is changed Task> ChangePasswordAsync(string oldPassword, string newPassword); @@ -299,6 +312,15 @@ public interface IInstaApi /// Return true if everything is ok Task> EditMediaAsync(string mediaId, string caption); + /// + /// Get feed of media your liked. + /// + /// Maximum count of pages to retrieve + /// + /// + /// + Task> GetLikeFeedAsync(int maxPages = 0); + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApi.cs b/InstaSharper/API/InstaApi.cs index 6030063f..a802cd7d 100644 --- a/InstaSharper/API/InstaApi.cs +++ b/InstaSharper/API/InstaApi.cs @@ -359,29 +359,24 @@ public async Task> GetUserFollowersAsync(string username, { if (maxPages == 0) maxPages = int.MaxValue; var user = await GetUserAsync(username); - var userFeedUri = UriCreator.GetUserFollowersUri(user.Value.Pk, _user.RankToken); - var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, userFeedUri, _deviceInfo); - var response = await _httpClient.SendAsync(request); - var json = await response.Content.ReadAsStringAsync(); + var userFollowersUri = UriCreator.GetUserFollowersUri(user.Value.Pk, _user.RankToken); var followers = new InstaUserList(); - if (response.StatusCode != HttpStatusCode.OK) return Result.Fail("", (InstaUserList)null); - var followersResponse = JsonConvert.DeserializeObject(json); - if (!followersResponse.IsOK()) - Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUserList)null); + var followersResponse = await GetUserListByURIAsync(userFollowersUri); + if (!followersResponse.Succeeded) + Result.Fail(followersResponse.Info, (InstaUserList)null); followers.AddRange( - followersResponse.Items.Select(ConvertersFabric.GetUserConverter) + followersResponse.Value.Items.Select(ConvertersFabric.GetUserConverter) .Select(converter => converter.Convert())); - if (!followersResponse.IsBigList) return Result.Success(followers); + if (!followersResponse.Value.IsBigList) return Result.Success(followers); var pages = 1; - while (!string.IsNullOrEmpty(followersResponse.NextMaxId) && pages < maxPages) + while (!string.IsNullOrEmpty(followersResponse.Value.NextMaxId) && pages < maxPages) { - var nextFollowers = Result.Success(followersResponse); - nextFollowers = await GetUserFollowersWithMaxIdAsync(username, nextFollowers.Value.NextMaxId); - if (!nextFollowers.Succeeded) - return Result.Success($"Not all pages was downloaded: {nextFollowers.Info.Message}", followers); - followersResponse = nextFollowers.Value; + var nextFollowersUri = UriCreator.GetUserFollowersUri(user.Value.Pk, _user.RankToken, followersResponse.Value.NextMaxId); + followersResponse = await GetUserListByURIAsync(nextFollowersUri); + if (!followersResponse.Succeeded) + return Result.Success($"Not all pages was downloaded: {followersResponse.Info.Message}", followers); followers.AddRange( - nextFollowers.Value.Items.Select(ConvertersFabric.GetUserConverter) + followersResponse.Value.Items.Select(ConvertersFabric.GetUserConverter) .Select(converter => converter.Convert())); pages++; } @@ -393,6 +388,44 @@ public async Task> GetUserFollowersAsync(string username, } } + public async Task> GetUserFollowingAsync(string username, int maxPages = 0) + { + ValidateUser(); + ValidateLoggedIn(); + try + { + if (maxPages == 0) maxPages = int.MaxValue; + var user = await GetUserAsync(username); + var userFeedUri = UriCreator.GetUserFollowingUri(user.Value.Pk, _user.RankToken); + var following = new InstaUserList(); + var userListResponse = await GetUserListByURIAsync(userFeedUri); + if (!userListResponse.Succeeded) + Result.Fail(userListResponse.Info, following); + following.AddRange( + userListResponse.Value.Items.Select(ConvertersFabric.GetUserConverter) + .Select(converter => converter.Convert())); + if (!userListResponse.Value.IsBigList) return Result.Success(following); + var pages = 1; + while (!string.IsNullOrEmpty(userListResponse.Value.NextMaxId) && pages < maxPages) + { + var nextUri = UriCreator.GetUserFollowingUri(user.Value.Pk, _user.RankToken, userListResponse.Value.NextMaxId); + userListResponse = await GetUserListByURIAsync(nextUri); + if (!userListResponse.Succeeded) + return Result.Success($"Not all pages was downloaded: {userListResponse.Info.Message}", following); + following.AddRange( + userListResponse.Value.Items.Select(ConvertersFabric.GetUserConverter) + .Select(converter => converter.Convert())); + pages++; + } + return Result.Success(following); + } + catch (Exception exception) + { + return Result.Fail(exception.Message, (InstaUserList)null); + } + } + + public async Task> GetCurrentUserFollowersAsync(int maxPages = 0) { ValidateUser(); @@ -929,7 +962,6 @@ public async Task> GetStoryTrayAsync() instaStoryTray = ConvertersFabric.GetStoryTrayConverter(instaStoryTrayResponse).Convert(); return Result.Success(instaStoryTray); - } catch (Exception exception) { @@ -956,7 +988,6 @@ public async Task> GetUserStoryAsync(long userId) userStory = ConvertersFabric.GetStoryConverter(userStoryResponse).Convert(); return Result.Success(userStory); - } catch (Exception exception) { @@ -974,9 +1005,9 @@ public async Task> UploadStoryPhotoAsync(MediaImage ima var uploadId = ApiRequestMessage.GenerateUploadId(); var requestContent = new MultipartFormDataContent(uploadId) { - { new StringContent(uploadId), "\"upload_id\"" }, - { new StringContent(_deviceInfo.DeviceGuid.ToString()), "\"_uuid\"" }, - { new StringContent(_user.CsrfToken), "\"_csrftoken\"" }, + {new StringContent(uploadId), "\"upload_id\""}, + {new StringContent(_deviceInfo.DeviceGuid.ToString()), "\"_uuid\""}, + {new StringContent(_user.CsrfToken), "\"_csrftoken\""}, { new StringContent("{\"lib_name\":\"jt\",\"lib_version\":\"1.3.0\",\"quality\":\"87\"}"), "\"image_compression\"" @@ -1016,11 +1047,10 @@ public async Task> ConfigureStoryPhotoAsync(MediaImage {"source_type", "1"}, {"caption", caption}, {"upload_id", uploadId}, - {"edits", new JObject { } }, - {"disable_comments", false }, + {"edits", new JObject()}, + {"disable_comments", false}, {"configure_mode", 1}, - {"camera_position", "unknown" } - + {"camera_position", "unknown"} }; var request = HttpHelper.GetSignedRequest(HttpMethod.Post, instaUri, _deviceInfo, data); var response = await _httpClient.SendAsync(request); @@ -1066,18 +1096,11 @@ public async Task> ChangePasswordAsync(string oldPassword, string var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); if (response.StatusCode == HttpStatusCode.OK) - { return Result.Success(true); //If status code is OK, then the password is surely changed - } - else - { - - var error = JsonConvert.DeserializeObject(json); - string errors = ""; - error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); - return Result.Fail(errors, false); - } - + var error = JsonConvert.DeserializeObject(json); + var errors = ""; + error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); + return Result.Fail(errors, false); } catch (Exception exception) { @@ -1110,15 +1133,10 @@ public async Task> DeleteMediaAsync(string mediaId, InstaMediaType var deletedResponse = JsonConvert.DeserializeObject(json); return Result.Success(deletedResponse.IsDeleted); } - else - { - - var error = JsonConvert.DeserializeObject(json); - string errors = ""; - error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); - return Result.Fail(errors, false); - } - + var error = JsonConvert.DeserializeObject(json); + var errors = ""; + error.Message.Errors.ForEach(errorContent => errors += errorContent + "\n"); + return Result.Fail(errors, false); } catch (Exception exception) { @@ -1147,15 +1165,9 @@ public async Task> EditMediaAsync(string mediaId, string caption) var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); if (response.StatusCode == HttpStatusCode.OK) - { return Result.Success(true); //Technically Instagram returns the InstaMediaItem, but it is useless in our case, at this time. - } //As the edited thing is simply a caption. No more. - else - { - var error = JsonConvert.DeserializeObject(json); - return Result.Fail(error.Message, false); - } - + var error = JsonConvert.DeserializeObject(json); + return Result.Fail(error.Message, false); } catch (Exception exception) { @@ -1163,6 +1175,32 @@ public async Task> EditMediaAsync(string mediaId, string caption) } } + public async Task> GetLikeFeedAsync(int maxPages = 0) + { + ValidateUser(); + if (maxPages == 0) maxPages = int.MaxValue; + var instaUri = UriCreator.GetUserLikeFeedUri(); + var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, instaUri, _deviceInfo); + var response = await _httpClient.SendAsync(request); + var json = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == HttpStatusCode.OK) + { + var mediaResponse = JsonConvert.DeserializeObject(json, + new InstaMediaListDataConverter()); + var moreAvailable = mediaResponse.MoreAvailable; + var converter = ConvertersFabric.GetMediaListConverter(mediaResponse); + var mediaList = converter.Convert(); + mediaList.Pages++; + var nextId = mediaResponse.NextMaxId; + while (moreAvailable && mediaList.Pages < maxPages) + { + + } + return Result.Success(mediaList); + } + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaMediaList)null); + } + #endregion #region private part @@ -1251,29 +1289,26 @@ private async Task> GetUserMediaListWithMaxIdAsy return Result.Fail("", (InstaMediaListResponse)null); } - private async Task> GetUserFollowersWithMaxIdAsync(string username, - string maxId) + private async Task> GetUserListByURIAsync(Uri uri) { ValidateUser(); try { if (!IsUserAuthenticated) throw new ArgumentException("user must be authenticated"); - var user = await GetUserAsync(username); - var userFeedUri = UriCreator.GetUserFollowersUri(user.Value.Pk, _user.RankToken, maxId); - var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, userFeedUri, _deviceInfo); + var request = HttpHelper.GetDefaultRequest(HttpMethod.Get, uri, _deviceInfo); var response = await _httpClient.SendAsync(request); var json = await response.Content.ReadAsStringAsync(); if (response.StatusCode == HttpStatusCode.OK) { - var followersResponse = JsonConvert.DeserializeObject(json); - if (!followersResponse.IsOK()) Result.Fail("", (InstaFollowersResponse)null); - return Result.Success(followersResponse); + var instaUserListResponse = JsonConvert.DeserializeObject(json); + if (!instaUserListResponse.IsOK()) Result.Fail("", (InstaUserListResponse)null); + return Result.Success(instaUserListResponse); } - return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaFollowersResponse)null); + return Result.Fail(GetBadStatusFromJsonString(json).Message, (InstaUserListResponse)null); } catch (Exception exception) { - return Result.Fail(exception.Message, (InstaFollowersResponse)null); + return Result.Fail(exception.Message, (InstaUserListResponse)null); } } @@ -1384,6 +1419,7 @@ private async Task> FollowUnfollowUserInternal(lo return Result.Fail(exception.Message, (InstaFriendshipStatus)null); } } + #endregion } } \ No newline at end of file diff --git a/InstaSharper/API/InstaApiConstants.cs b/InstaSharper/API/InstaApiConstants.cs index 809365ec..881744c8 100644 --- a/InstaSharper/API/InstaApiConstants.cs +++ b/InstaSharper/API/InstaApiConstants.cs @@ -25,6 +25,7 @@ internal static class InstaApiConstants public const string GET_USER_TAGS = API_SUFFIX + "/v1/usertags/{0}/feed/"; public const string GET_MEDIA = API_SUFFIX + "/v1/media/{0}/info/"; public const string GET_USER_FOLLOWERS = API_SUFFIX + "/v1/friendships/{0}/followers/?rank_token={1}"; + public const string GET_USER_FOLLOWING = API_SUFFIX + "/v1/friendships/{0}/following/?rank_token={1}"; public const string GET_TAG_FEED = API_SUFFIX + "/v1/feed/tag/{0}"; public const string GET_RANKED_RECIPIENTS = API_SUFFIX + "/v1/direct_v2/ranked_recipients"; public const string GET_RECENT_RECIPIENTS = API_SUFFIX + "/v1/direct_share/recent_recipients/"; @@ -52,10 +53,8 @@ internal static class InstaApiConstants public const string GET_STORY_TRAY = API_SUFFIX + "/v1/feed/reels_tray/"; public const string GET_USER_STORY = API_SUFFIX + "/v1/feed/user/{0}/reel_media/"; public const string STORY_CONFIGURE = API_SUFFIX + "/v1/media/configure_to_reel/"; - - public const string LOCATION_SEARCH = API_SUFFIX + "/v1/location_search/"; /* To implement */ - - + public const string LOCATION_SEARCH = API_SUFFIX + "/v1/location_search/"; + public static string LIKE_FEED = API_SUFFIX + "/v1/feed/liked/"; public const string HEADER_USER_AGENT = "User-Agent"; public const string USER_AGENT = @@ -65,7 +64,6 @@ internal static class InstaApiConstants public const string HEADER_QUERY = "q"; public const string HEADER_RANK_TOKEN = "rank_token"; public const string HEADER_COUNT = "count"; - public const string IG_SIGNATURE_KEY = "b03e0daaf2ab17cda2a569cace938d639d1288a1197f9ecf97efd0a4ec0874d7"; public const string HEADER_IG_SIGNATURE = "signed_body"; public const string IG_SIGNATURE_KEY_VERSION = "4"; @@ -83,7 +81,6 @@ internal static class InstaApiConstants public const string HEADER_TIMEZONE = "timezone_offset"; public const string HEADER_XGOOGLE_AD_IDE = "X-Google-AD-ID"; public const string COMMENT_BREADCRUMB_KEY = "iN4$aGr0m"; - public const int TIMEZONE_OFFSET = 43200; } } \ No newline at end of file diff --git a/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs b/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs index 56a1ae4c..20f25eab 100644 --- a/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs +++ b/InstaSharper/Classes/Android/DeviceInfo/AndroidDeviceGenerator.cs @@ -360,7 +360,6 @@ public class AndroidDeviceGenerator DeviceGuid = new Guid("fe46d44b-e00c-4f1b-9718-7c4dae2160cc"), PhoneGuid = new Guid("0bcbf7e0-a73f-4424-8c70-c2d38ae42d5d"), DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("fe46d44b-e00c-4f1b-9718-7c4dae2160cc")) - } }, { @@ -382,7 +381,6 @@ public class AndroidDeviceGenerator DeviceGuid = new Guid("2c4ae214-c037-486c-a335-76a1f6973445"), PhoneGuid = new Guid("7fb2eb38-04ab-4c51-bd0c-694c7da2187e"), DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("2c4ae214-c037-486c-a335-76a1f6973445")) - } }, @@ -405,7 +403,6 @@ public class AndroidDeviceGenerator DeviceGuid = new Guid("7f585e77-becf-4137-bf1f-84ab72e35eb4"), PhoneGuid = new Guid("28484284-e646-4a29-88fc-76c2666d5ab3"), DeviceId = ApiRequestMessage.GenerateDeviceIdFromGuid(new Guid("7f585e77-becf-4137-bf1f-84ab72e35eb4")) - } }, { @@ -442,7 +439,6 @@ public static AndroidDevice GetRandomAndroidDevice() public static AndroidDevice GetByName(string name) { return AndroidAndroidDeviceSets[name]; - } public static AndroidDevice GetById(string deviceId) diff --git a/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs b/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs index f1917b6a..ebd2afb6 100644 --- a/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs +++ b/InstaSharper/Classes/Android/DeviceInfo/ApiRequestMessage.cs @@ -41,13 +41,13 @@ internal static string GenerateDeviceId() internal static string GenerateUploadId() { var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0); - var uploadId = (long)timeSpan.TotalSeconds; + var uploadId = (long) timeSpan.TotalSeconds; return uploadId.ToString(); } public static ApiRequestMessage FromDevice(AndroidDevice device) { - var requestMessage = new ApiRequestMessage() + var requestMessage = new ApiRequestMessage { phone_id = device.PhoneGuid.ToString(), guid = device.DeviceGuid, diff --git a/InstaSharper/Classes/Models/InstaCarousel.cs b/InstaSharper/Classes/Models/InstaCarousel.cs index 9ccc1254..2b8605db 100644 --- a/InstaSharper/Classes/Models/InstaCarousel.cs +++ b/InstaSharper/Classes/Models/InstaCarousel.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace InstaSharper.Classes.Models { diff --git a/InstaSharper/Classes/Models/InstaMedia.cs b/InstaSharper/Classes/Models/InstaMedia.cs index 7a6fcc77..632faf45 100644 --- a/InstaSharper/Classes/Models/InstaMedia.cs +++ b/InstaSharper/Classes/Models/InstaMedia.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using InstaSharper.Converters; namespace InstaSharper.Classes.Models { diff --git a/InstaSharper/Classes/Models/InstaStoryItem.cs b/InstaSharper/Classes/Models/InstaStoryItem.cs index c98f7624..3591ec25 100644 --- a/InstaSharper/Classes/Models/InstaStoryItem.cs +++ b/InstaSharper/Classes/Models/InstaStoryItem.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace InstaSharper.Classes.Models { @@ -58,26 +57,26 @@ public class InstaStoryItem public bool PhotoOfYou { get; set; } - #region Video - - public List VideoVersions { get; set; } = new List(); //Visible only if the story is a video. - - public bool HasAudio { get; set; } //Visible only if the story is a video. - - public double VideoDuration { get; set; } //Visible only if the story is a video. - - #endregion - public bool CanViewerSave { get; set; } public DateTime ExpiringAt { get; set; } - public bool IsReelMedia { get; set; } + public bool IsReelMedia { get; set; } //public List ReelMentions { get; set; } --- --- //I'll do a test via Fiddler //public List StoryLocation { get; set; } //public List StoryHashtags { get; set; } //I'll do a test via Fiddler + + #region Video + + public List VideoVersions { get; set; } = new List(); //Visible only if the story is a video. + + public bool HasAudio { get; set; } //Visible only if the story is a video. + + public double VideoDuration { get; set; } //Visible only if the story is a video. + + #endregion } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/Models/InstaStoryMedia.cs b/InstaSharper/Classes/Models/InstaStoryMedia.cs index 4d93cfb6..de7f0c65 100644 --- a/InstaSharper/Classes/Models/InstaStoryMedia.cs +++ b/InstaSharper/Classes/Models/InstaStoryMedia.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace InstaSharper.Classes.Models +namespace InstaSharper.Classes.Models { public class InstaStoryMedia { public InstaStoryItem Media { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/Models/InstaStoryTray.cs b/InstaSharper/Classes/Models/InstaStoryTray.cs index 1bf6ebdb..2be9646c 100644 --- a/InstaSharper/Classes/Models/InstaStoryTray.cs +++ b/InstaSharper/Classes/Models/InstaStoryTray.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; namespace InstaSharper.Classes.Models { @@ -16,4 +14,4 @@ public class InstaStoryTray public string Status { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/Models/MediaVideo.cs b/InstaSharper/Classes/Models/MediaVideo.cs index 2edd854e..7cd4ad9e 100644 --- a/InstaSharper/Classes/Models/MediaVideo.cs +++ b/InstaSharper/Classes/Models/MediaVideo.cs @@ -2,7 +2,6 @@ { public class MediaVideo { - public MediaVideo(string url, string width, string height, int type) { Url = url; @@ -18,6 +17,5 @@ public MediaVideo(string url, string width, string height, int type) public string Height { get; set; } public int Type { get; set; } - } } \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseType.cs b/InstaSharper/Classes/ResponseType.cs index b194d746..bdd22d51 100644 --- a/InstaSharper/Classes/ResponseType.cs +++ b/InstaSharper/Classes/ResponseType.cs @@ -6,6 +6,7 @@ public enum ResponseType LoginRequired = 1, CheckPointRequired = 2, RequestsLimit = 3, - SentryBlock = 4 + SentryBlock = 4, + OK = 5 } } \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs b/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs index a7cb5a89..59416f70 100644 --- a/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/BadStatusErrorsResponse.cs @@ -1,8 +1,6 @@ -using InstaSharper.Classes.ResponseWrappers.BaseResponse; +using System.Collections.Generic; +using InstaSharper.Classes.ResponseWrappers.BaseResponse; using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; namespace InstaSharper.Classes.ResponseWrappers { @@ -17,4 +15,4 @@ public class MessageErrorsResponse [JsonProperty("errors")] public List Errors { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs b/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs index 32a24ff3..05ed9e0a 100644 --- a/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/DeleteResponse.cs @@ -1,13 +1,11 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; +using InstaSharper.Classes.ResponseWrappers.BaseResponse; +using Newtonsoft.Json; namespace InstaSharper.Classes.ResponseWrappers { - class DeleteResponse : BaseResponse.BaseStatusResponse + internal class DeleteResponse : BaseStatusResponse { [JsonProperty("did_delete")] public bool IsDeleted { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/ImageResponse.cs b/InstaSharper/Classes/ResponseWrappers/ImageResponse.cs index e2aacfbe..c9a2a388 100644 --- a/InstaSharper/Classes/ResponseWrappers/ImageResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/ImageResponse.cs @@ -4,7 +4,7 @@ namespace InstaSharper.Classes.ResponseWrappers { internal class ImageResponse { - [JsonProperty("uri")] + [JsonProperty("url")] public string Url { get; set; } [JsonProperty("width")] diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs index 03314ba1..c9c75fb2 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryItemResponse.cs @@ -1,7 +1,5 @@ -using System; +using System.Collections.Generic; using InstaSharper.Classes.Models; -using System.Collections.Generic; -using System.Text; using Newtonsoft.Json; namespace InstaSharper.Classes.ResponseWrappers @@ -88,19 +86,6 @@ internal class InstaStoryItemResponse [JsonProperty("photo_of_you")] public bool PhotoOfYou { get; set; } - #region Video - - [JsonProperty("video_versions")] - public InstaVideoCandidatesResponse VideoVersions { get; set; } //Visible only if the story is a video. - - [JsonProperty("has_audio")] - public bool HasAudio { get; set; } //Visible only if the story is a video. - - [JsonProperty("video_duration")] - public double VideoDuration { get; set; } //Visible only if the story is a video. - - #endregion - [JsonProperty("can_viewer_save")] public bool CanViewerSave { get; set; } @@ -113,8 +98,22 @@ internal class InstaStoryItemResponse //public List ReelMentions { get; set; } --- --- //I'll do a test via Fiddler //[JsonProperty("story_locations")] + //public List StoryLocation { get; set; } //public List StoryHashtags { get; set; } //I'll do a test via Fiddler + + #region Video + + [JsonProperty("video_versions")] + public InstaVideoCandidatesResponse VideoVersions { get; set; } //Visible only if the story is a video. + + [JsonProperty("has_audio")] + public bool HasAudio { get; set; } //Visible only if the story is a video. + + [JsonProperty("video_duration")] + public double VideoDuration { get; set; } //Visible only if the story is a video. + + #endregion } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs index 2f6ff04a..34241572 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryMediaResponse.cs @@ -1,13 +1,10 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; namespace InstaSharper.Classes.ResponseWrappers { - class InstaStoryMediaResponse + internal class InstaStoryMediaResponse { [JsonProperty("media")] public InstaStoryItemResponse Media { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs index e4adf1c0..e8bf718d 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryResponse.cs @@ -1,6 +1,5 @@ -using InstaSharper.Classes.Models; +using System.Collections.Generic; using Newtonsoft.Json; -using System.Collections.Generic; namespace InstaSharper.Classes.ResponseWrappers { diff --git a/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs index 3aef336c..d1fa2656 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaStoryTrayResponse.cs @@ -1,12 +1,9 @@ -using InstaSharper.Classes.Models; +using System.Collections.Generic; using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; namespace InstaSharper.Classes.ResponseWrappers { - class InstaStoryTrayResponse + internal class InstaStoryTrayResponse { [JsonProperty("tray")] public List Tray { get; set; } @@ -22,4 +19,4 @@ class InstaStoryTrayResponse [JsonProperty("status")] public string Status { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/ResponseWrappers/InstaFollowersResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaUserListResponse.cs similarity index 91% rename from InstaSharper/Classes/ResponseWrappers/InstaFollowersResponse.cs rename to InstaSharper/Classes/ResponseWrappers/InstaUserListResponse.cs index 80b9d086..809fce28 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaFollowersResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaUserListResponse.cs @@ -4,7 +4,7 @@ namespace InstaSharper.Classes.ResponseWrappers { - internal class InstaFollowersResponse : BaseStatusResponse + internal class InstaUserListResponse : BaseStatusResponse { [JsonProperty("users")] public List Items { get; set; } diff --git a/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs b/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs index d37f7e51..3cb1cf0a 100644 --- a/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs +++ b/InstaSharper/Classes/ResponseWrappers/InstaVideoCandidatesResponse.cs @@ -1,11 +1,9 @@ -using InstaSharper.Classes.Models; -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; +using InstaSharper.Classes.Models; namespace InstaSharper.Classes.ResponseWrappers { - class InstaVideoCandidatesResponse : List + internal class InstaVideoCandidatesResponse : List { } -} +} \ No newline at end of file diff --git a/InstaSharper/Classes/Result.cs b/InstaSharper/Classes/Result.cs index 09a20498..4c905662 100644 --- a/InstaSharper/Classes/Result.cs +++ b/InstaSharper/Classes/Result.cs @@ -31,21 +31,38 @@ public Result(bool succeeded, T value) public static class Result { public static IResult Success(T resValue) - => new Result(true, resValue); + { + return new Result(true, resValue, new ResultInfo(ResponseType.OK, "No errors detected")); + } public static IResult Success(string successMsg, T resValue) - => new Result(true, resValue, new ResultInfo(successMsg)); + { + return new Result(true, resValue, new ResultInfo(ResponseType.OK, successMsg)); + } public static IResult Fail(Exception exception) - => new Result(false, default(T), new ResultInfo(exception)); + { + return new Result(false, default(T), new ResultInfo(exception)); + } public static IResult Fail(string errMsg) - => new Result(false, default(T), new ResultInfo(errMsg)); + { + return new Result(false, default(T), new ResultInfo(errMsg)); + } public static IResult Fail(string errMsg, T resValue) - => new Result(false, resValue, new ResultInfo(errMsg)); + { + return new Result(false, resValue, new ResultInfo(errMsg)); + } + + public static IResult Fail(ResultInfo info, T resValue) + { + return new Result(false, resValue, info); + } public static IResult Fail(string errMsg, ResponseType responseType, T resValue) - => new Result(false, resValue, new ResultInfo(responseType, errMsg)); + { + return new Result(false, resValue, new ResultInfo(responseType, errMsg)); + } } } \ No newline at end of file diff --git a/InstaSharper/Converters/ConvertersFabric.cs b/InstaSharper/Converters/ConvertersFabric.cs index 8edb539f..4d98d2f9 100644 --- a/InstaSharper/Converters/ConvertersFabric.cs +++ b/InstaSharper/Converters/ConvertersFabric.cs @@ -113,22 +113,22 @@ public static IObjectConverter Get public static IObjectConverter GetStoryItemConverter(InstaStoryItemResponse storyItem) { - return new InstaStoryItemConverter { SourceObject = storyItem }; + return new InstaStoryItemConverter {SourceObject = storyItem}; } public static IObjectConverter GetStoryConverter(InstaStoryResponse storyItem) { - return new InstaStoryConverter { SourceObject = storyItem }; + return new InstaStoryConverter {SourceObject = storyItem}; } public static IObjectConverter GetStoryTrayConverter(InstaStoryTrayResponse storyTray) { - return new InstaStoryTrayConverter { SourceObject = storyTray }; + return new InstaStoryTrayConverter {SourceObject = storyTray}; } public static IObjectConverter GetStoryMediaConverter(InstaStoryMediaResponse storyMedia) { - return new InstaStoryMediaConverter { SourceObject = storyMedia }; + return new InstaStoryMediaConverter {SourceObject = storyMedia}; } } } \ No newline at end of file diff --git a/InstaSharper/Converters/InstaStoryMediaConverter.cs b/InstaSharper/Converters/InstaStoryMediaConverter.cs index 03973ea6..034b0f35 100644 --- a/InstaSharper/Converters/InstaStoryMediaConverter.cs +++ b/InstaSharper/Converters/InstaStoryMediaConverter.cs @@ -1,12 +1,9 @@ using InstaSharper.Classes.Models; using InstaSharper.Classes.ResponseWrappers; -using System; -using System.Collections.Generic; -using System.Text; namespace InstaSharper.Converters { - class InstaStoryMediaConverter : IObjectConverter + internal class InstaStoryMediaConverter : IObjectConverter { public InstaStoryMediaResponse SourceObject { get; set; } @@ -20,4 +17,4 @@ public InstaStoryMedia Convert() return instaStoryMedia; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Converters/InstaStoryTrayConverter.cs b/InstaSharper/Converters/InstaStoryTrayConverter.cs index 444815e7..cc74218d 100644 --- a/InstaSharper/Converters/InstaStoryTrayConverter.cs +++ b/InstaSharper/Converters/InstaStoryTrayConverter.cs @@ -7,12 +7,13 @@ namespace InstaSharper.Converters internal class InstaStoryTrayConverter : IObjectConverter { public InstaStoryTrayResponse SourceObject { get; set; } - + public InstaStoryTray Convert() { if (SourceObject == null) throw new ArgumentNullException($"Source object"); - var storyTray = new InstaStoryTray { + var storyTray = new InstaStoryTray + { Status = SourceObject.Status, StickerVersion = SourceObject.StickerVersion, StoryRankingToken = SourceObject.StoryRankingToken diff --git a/InstaSharper/Converters/Json/InstaCommentDataConverter.cs b/InstaSharper/Converters/Json/InstaCommentDataConverter.cs index 5270e8d2..7a8b821f 100644 --- a/InstaSharper/Converters/Json/InstaCommentDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaCommentDataConverter.cs @@ -12,7 +12,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaCommentResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var root = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaFeedResponseDataConverter.cs b/InstaSharper/Converters/Json/InstaFeedResponseDataConverter.cs index 12132afd..88466a8e 100644 --- a/InstaSharper/Converters/Json/InstaFeedResponseDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaFeedResponseDataConverter.cs @@ -13,7 +13,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaFeedResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaFriendShipDataConverter.cs b/InstaSharper/Converters/Json/InstaFriendShipDataConverter.cs index 3a6f40a1..89ab49b5 100644 --- a/InstaSharper/Converters/Json/InstaFriendShipDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaFriendShipDataConverter.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using InstaSharper.Classes.ResponseWrappers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -15,7 +12,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaFriendshipStatusResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var root = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaMediaListDataConverter.cs b/InstaSharper/Converters/Json/InstaMediaListDataConverter.cs index 0fcf6930..458135d7 100644 --- a/InstaSharper/Converters/Json/InstaMediaListDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaMediaListDataConverter.cs @@ -12,7 +12,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaMediaListResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var root = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaRecentActivityConverter.cs b/InstaSharper/Converters/Json/InstaRecentActivityConverter.cs index f03a815d..b1856c3a 100644 --- a/InstaSharper/Converters/Json/InstaRecentActivityConverter.cs +++ b/InstaSharper/Converters/Json/InstaRecentActivityConverter.cs @@ -13,7 +13,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaRecentActivityResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaRecipientsDataConverter.cs b/InstaSharper/Converters/Json/InstaRecipientsDataConverter.cs index a7e60279..affab5bb 100644 --- a/InstaSharper/Converters/Json/InstaRecipientsDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaRecipientsDataConverter.cs @@ -19,7 +19,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaRecipientsResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var root = JToken.Load(reader); diff --git a/InstaSharper/Converters/Json/InstaThreadDataConverter.cs b/InstaSharper/Converters/Json/InstaThreadDataConverter.cs index 6ebd27bf..b3469846 100644 --- a/InstaSharper/Converters/Json/InstaThreadDataConverter.cs +++ b/InstaSharper/Converters/Json/InstaThreadDataConverter.cs @@ -12,7 +12,9 @@ public override bool CanConvert(Type objectType) return objectType == typeof(InstaDirectInboxThreadResponse); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + public override object ReadJson(JsonReader reader, + Type objectType, + object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); diff --git a/InstaSharper/Helpers/HttpHelper.cs b/InstaSharper/Helpers/HttpHelper.cs index 37d4ccbe..7b4318d6 100644 --- a/InstaSharper/Helpers/HttpHelper.cs +++ b/InstaSharper/Helpers/HttpHelper.cs @@ -22,7 +22,9 @@ public static HttpRequestMessage GetDefaultRequest(HttpMethod method, Uri uri, A return request; } - public static HttpRequestMessage GetSignedRequest(HttpMethod method, Uri uri, AndroidDevice deviceInfo, + public static HttpRequestMessage GetSignedRequest(HttpMethod method, + Uri uri, + AndroidDevice deviceInfo, Dictionary data) { var hash = CryptoHelper.CalculateHash(InstaApiConstants.IG_SIGNATURE_KEY, @@ -43,7 +45,9 @@ public static HttpRequestMessage GetSignedRequest(HttpMethod method, Uri uri, An return request; } - public static HttpRequestMessage GetSignedRequest(HttpMethod method, Uri uri, AndroidDevice deviceInfo, + public static HttpRequestMessage GetSignedRequest(HttpMethod method, + Uri uri, + AndroidDevice deviceInfo, JObject data) { var hash = CryptoHelper.CalculateHash(InstaApiConstants.IG_SIGNATURE_KEY, diff --git a/InstaSharper/Helpers/InstaProxy.cs b/InstaSharper/Helpers/InstaProxy.cs index 5dbd5c8e..098b1096 100644 --- a/InstaSharper/Helpers/InstaProxy.cs +++ b/InstaSharper/Helpers/InstaProxy.cs @@ -26,4 +26,4 @@ public bool IsBypassed(Uri host) public ICredentials Credentials { get; set; } } -} +} \ No newline at end of file diff --git a/InstaSharper/Helpers/UriCreator.cs b/InstaSharper/Helpers/UriCreator.cs index d634643d..9d8abbbc 100644 --- a/InstaSharper/Helpers/UriCreator.cs +++ b/InstaSharper/Helpers/UriCreator.cs @@ -21,7 +21,7 @@ public static Uri GetUserUri(string username) Uri instaUri; if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.SEARCH_USERS, out instaUri)) throw new Exception("Cant create search user URI"); - var userUriBuilder = new UriBuilder(instaUri) {Query = $"q={username}"}; + var userUriBuilder = new UriBuilder(instaUri) { Query = $"q={username}" }; return userUriBuilder.Uri; } @@ -54,7 +54,7 @@ public static Uri GetTimelineWithMaxIdUri(string nextId) Uri instaUri; if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.TIMELINEFEED, out instaUri)) throw new Exception("Cant create search URI for timeline"); - var uriBuilder = new UriBuilder(instaUri) {Query = $"max_id={nextId}"}; + var uriBuilder = new UriBuilder(instaUri) { Query = $"max_id={nextId}" }; return uriBuilder.Uri; } @@ -64,7 +64,7 @@ public static Uri GetMediaListWithMaxIdUri(string userPk, string nextId) if ( !Uri.TryCreate(new Uri(InstaApiConstants.INSTAGRAM_URL), InstaApiConstants.USEREFEED + userPk, out instaUri)) throw new Exception("Cant create URI for media list"); - var uriBuilder = new UriBuilder(instaUri) {Query = $"max_id={nextId}"}; + var uriBuilder = new UriBuilder(instaUri) { Query = $"max_id={nextId}" }; return uriBuilder.Uri; } @@ -83,7 +83,18 @@ internal static Uri GetUserFollowersUri(string userPk, string rankToken, string !Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.GET_USER_FOLLOWERS, userPk, rankToken), out instaUri)) throw new Exception("Cant create URI for user followers"); if (string.IsNullOrEmpty(maxId)) return instaUri; - var uriBuilder = new UriBuilder(instaUri) {Query = $"max_id={maxId}"}; + var uriBuilder = new UriBuilder(instaUri) { Query = $"max_id={maxId}" }; + return uriBuilder.Uri; + } + + internal static Uri GetUserFollowingUri(string userPk, string rankToken, string maxId = "") + { + Uri instaUri; + if ( + !Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.GET_USER_FOLLOWING, userPk, rankToken), + out instaUri)) throw new Exception("Cant create URI for user following"); + if (string.IsNullOrEmpty(maxId)) return instaUri; + var uriBuilder = new UriBuilder(instaUri) { Query = $"max_id={maxId}" }; return uriBuilder.Uri; } @@ -143,7 +154,7 @@ public static Uri GetUserTagsUri(string userPk, string rankToken, string maxId = throw new Exception("Cant create URI for get user tags"); var query = $"rank_token={rankToken}&ranked_content=true"; if (!string.IsNullOrEmpty(maxId)) query += $"max_id={maxId}"; - var uriBuilder = new UriBuilder(instaUri) {Query = query}; + var uriBuilder = new UriBuilder(instaUri) { Query = query }; return uriBuilder.Uri; } @@ -169,7 +180,7 @@ public static Uri GetRecentActivityUri() if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.GET_RECENT_ACTIVITY, out instaUri)) throw new Exception("Cant create URI (get recent activity)"); var query = $"activity_module=all"; - var uriBuilder = new UriBuilder(instaUri) {Query = query}; + var uriBuilder = new UriBuilder(instaUri) { Query = query }; return uriBuilder.Uri; } @@ -180,7 +191,7 @@ public static Uri GetFollowingRecentActivityUri(string maxId = null) throw new Exception("Cant create URI (get following recent activity"); var query = string.Empty; if (!string.IsNullOrEmpty(maxId)) query += $"max_id={maxId}"; - var uriBuilder = new UriBuilder(instaUri) {Query = query}; + var uriBuilder = new UriBuilder(instaUri) { Query = query }; return uriBuilder.Uri; } @@ -314,7 +325,7 @@ public static Uri GetStoryTray() public static Uri GetUserStoryUri(long userId) { - if (!Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.GET_USER_STORY, userId), + if (!Uri.TryCreate(BaseInstagramUri, string.Format(InstaApiConstants.GET_USER_STORY, userId), out var instaUri)) throw new Exception("Can't create URI for getting user's story"); return instaUri; @@ -347,5 +358,15 @@ public static Uri GetEditMediaUri(string mediaId) throw new Exception("Can't create URI for editing media"); return instaUri; } + + public static Uri GetUserLikeFeedUri(string maxId = null) + { + if (!Uri.TryCreate(BaseInstagramUri, InstaApiConstants.LIKE_FEED, out var instaUri)) + throw new Exception("Can't create URI for getting like feed"); + var query = string.Empty; + if (!string.IsNullOrEmpty(maxId)) query += $"max_id={maxId}"; + var uriBuilder = new UriBuilder(instaUri) { Query = query }; + return uriBuilder.Uri; + } } } \ No newline at end of file From ac69997d5264e10eec433c618f6f40e776537e3f Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Sun, 11 Jun 2017 20:27:58 +0300 Subject: [PATCH 14/17] 1.2.5 --- InstaSharper/InstaSharper.csproj | 2 ++ README.md | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/InstaSharper/InstaSharper.csproj b/InstaSharper/InstaSharper.csproj index c074603e..8ef70459 100644 --- a/InstaSharper/InstaSharper.csproj +++ b/InstaSharper/InstaSharper.csproj @@ -11,6 +11,8 @@ false false false + True + 1.2.5 diff --git a/README.md b/README.md index f256f116..d42772c7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Note that: there is a simple [Instagram API](https://github.com/a-legotin/Instag [![Telegram chat](https://img.shields.io/badge/telegram-channel-blue.svg)](https://t.me/instasharper) [![GitHub stars](https://img.shields.io/github/stars/a-legotin/InstaSharper.svg)](https://github.com/a-legotin/InstaSharper/stargazers) -#### Current version: 1.2.4 [Stable], 1.2.5 [Under development] +#### Current version: 1.2.5 [Stable], 1.2.6 [Under development] ## Overview This project intends to provide all the features available in the Instagram API up to v10.3.2. It is being developed in C# for .NET Framework 4.5.2 and .NET Standart 1.6 @@ -61,17 +61,17 @@ Currently the library supports following coverage of the following Instagram API - [x] Send comment - [x] Delete comment - [x] Upload photo +- [x] Get followings list +- [x] Delete media (photo/video) +- [x] Upload story (photo) +- [x] Change password +- [x] Upload video -- [ ] Get followings list -- [ ] Delete media (photo/video) -- [ ] Upload story (photo) -- [ ] Change password * Get user list autocomplete * Register new user * Get megaphone log * Explore feed -* Upload video * Get full account backup * Send direct message * Edit media From 947581fbd943d405eb28d59d4becc16fe5519a1b Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Sun, 11 Jun 2017 20:58:53 +0300 Subject: [PATCH 15/17] app veyor --- InstaSharper.Tests/InstaSharper.Tests.csproj | 8 ++++---- appveyor.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/InstaSharper.Tests/InstaSharper.Tests.csproj b/InstaSharper.Tests/InstaSharper.Tests.csproj index 8b412454..f81ce087 100644 --- a/InstaSharper.Tests/InstaSharper.Tests.csproj +++ b/InstaSharper.Tests/InstaSharper.Tests.csproj @@ -18,13 +18,13 @@ - - PreserveNewest - + - + + PreserveNewest + diff --git a/appveyor.yml b/appveyor.yml index 95e1e1f7..c2c3384b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.2.4.{build} +version: 1.2.5 os: Visual Studio 2017 platform: Any CPU configuration: Release @@ -13,9 +13,9 @@ skip_commits: skip_tags: true build: - publish_nuget: true # package projects with .nuspec files and push to artifacts - publish_nuget_symbols: true # generate and publish NuGet symbol packages - include_nuget_references: true # add -IncludeReferencedProjects option while packaging NuGet artifacts + publish_nuget: false # package projects with .nuspec files and push to artifacts + publish_nuget_symbols: false # generate and publish NuGet symbol packages + include_nuget_references: false # add -IncludeReferencedProjects option while packaging NuGet artifacts build_script: - ps: nuget sources add -Name MyGetXunit -Source https://www.myget.org/F/xunit/api/v3/index.json From 78021ab2aa93cdfc2ab26aef74ddaff29c9d0108 Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Sun, 11 Jun 2017 21:00:06 +0300 Subject: [PATCH 16/17] skip packing --- appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c2c3384b..2e7e4012 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,8 +22,6 @@ build_script: - ps: dotnet --info - ps: dotnet restore - ps: dotnet build - - ps: cd InstaSharper - - ps: dotnet pack -o ../nugetpack -c release environment: instaapiuserpassword: From c8f2942bc9d7b13f313f8aba14c9dd133bb1be42 Mon Sep 17 00:00:00 2001 From: Alexander Legotin Date: Sun, 11 Jun 2017 21:00:57 +0300 Subject: [PATCH 17/17] build version --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2e7e4012..408b7f7b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.2.5 +version: 1.2.5.{build} os: Visual Studio 2017 platform: Any CPU configuration: Release