Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/BatchOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@
throw StreamException.FromResponse(response);
}

public async Task<ResponseBase> UnfollowManyAsync(IEnumerable<UnfollowRelation> unfollows)
{
var request = _client.BuildAppRequest("unfollow_many/", HttpMethod.Post);

Check warning on line 62 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check warning on line 62 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

// Create a new anonymous object array with the properties expected by the API
var unfollowRequests = unfollows.Select(f => new

Check warning on line 64 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check warning on line 64 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

{
source = f.Source,
target = f.Target,
keep_history = f.KeepHistory
});

Check warning on line 70 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check warning on line 70 in src/BatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

request.SetJsonBody(StreamJsonConverter.SerializeObject(unfollowRequests));

var response = await _client.MakeRequestAsync(request);

if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.OK)
return StreamJsonConverter.DeserializeObject<ResponseBase>(response.Content);

throw StreamException.FromResponse(response);
}

public async Task<GenericGetResponse<Activity>> GetActivitiesByIdAsync(IEnumerable<string> ids)
=> await GetActivitiesAsync(ids, null);

Expand Down
4 changes: 4 additions & 0 deletions src/IBatchOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
/// <summary>Follow muiltiple feeds.</summary>
/// <remarks>https://getstream.io/activity-feeds/docs/dotnet-csharp/add_many_activities/?language=csharp</remarks>
Task<ResponseBase> FollowManyAsync(IEnumerable<Follow> follows, int activityCopyLimit = 100);

Check warning on line 24 in src/IBatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check warning on line 24 in src/IBatchOperations.cs

View workflow job for this annotation

GitHub Actions / Run tests

/// <summary>Unfollow multiple feeds in a single request using UnfollowRelation objects.</summary>
/// <remarks>https://getstream.io/activity-feeds/docs/dotnet-csharp/add_many_activities/?language=csharp</remarks>
Task<ResponseBase> UnfollowManyAsync(IEnumerable<UnfollowRelation> unfollows);

/// <summary>Get multiple activities by activity ids.</summary>
/// <remarks>https://getstream.io/activity-feeds/docs/dotnet-csharp/add_many_activities/?language=csharp</remarks>
Expand Down
49 changes: 49 additions & 0 deletions src/Models/UnfollowRelation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace Stream.Models
{
/// <summary>
/// Represents a relationship to unfollow in batch operations
/// </summary>
public class UnfollowRelation
{
/// <summary>
/// Source feed id
/// </summary>
public string Source { get; set; }

Check warning on line 12 in src/Models/UnfollowRelation.cs

View workflow job for this annotation

GitHub Actions / Run tests

/// <summary>
/// Target feed id
/// </summary>
public string Target { get; set; }

/// <summary>
/// Whether to keep activities from the unfollowed feed
/// </summary>
public bool KeepHistory { get; set; }

/// <summary>
/// Creates a new instance of the UnfollowRelation class
/// </summary>
/// <param name="source">Source feed id</param>
/// <param name="target">Target feed id</param>
/// <param name="keepHistory">Whether to keep activities from the unfollowed feed</param>
public UnfollowRelation(string source, string target, bool keepHistory = false)
{
Source = source;
Target = target;
KeepHistory = keepHistory;
}

/// <summary>
/// Creates a new instance of the UnfollowRelation class
/// </summary>
/// <param name="source">Source feed</param>
/// <param name="target">Target feed</param>
/// <param name="keepHistory">Whether to keep activities from the unfollowed feed</param>
public UnfollowRelation(IStreamFeed source, IStreamFeed target, bool keepHistory = false)
{
Source = source.FeedId;
Target = target.FeedId;
KeepHistory = keepHistory;
}
}
}
110 changes: 110 additions & 0 deletions tests/BatchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ namespace StreamNetTests
[TestFixture]
public class BatchTests : TestBase
{
[Test]
public void TestUnfollowManyArgumentValidation()
{
// Should work with empty array
Assert.DoesNotThrowAsync(async () =>
{
await Client.Batch.UnfollowManyAsync(new UnfollowRelation[] { });
});

// Should work with valid unfollow relation objects
Assert.DoesNotThrowAsync(async () =>
{
await Client.Batch.UnfollowManyAsync(new[] { new UnfollowRelation("user:1", "user:2", false) });
});

// Should work with keepHistory true
Assert.DoesNotThrowAsync(async () =>
{
await Client.Batch.UnfollowManyAsync(new[] { new UnfollowRelation("user:1", "user:2", true) });
});
}

[Test]
public void TestGetEnrichedActivitiesArgumentValidation()
{
Expand Down Expand Up @@ -305,5 +327,93 @@ public async Task TestBatchActivityForeignIdTime()

Assert.AreEqual(1, result.Results.Count);
}

[Test]
public async Task TestBatchUnfollowManyKeepHistoryFalse()
{
// First set up follows and add activities
await Client.Batch.FollowManyAsync(new[]
{
new Follow(UserFeed, FlatFeed),
new Follow(UserFeed2, FlatFeed),
});

var newActivity = new Activity("1", "test", "1");
var response = await this.FlatFeed.AddActivityAsync(newActivity);

// Verify follows are working
var activities1 = (await this.UserFeed.GetActivitiesAsync(0, 1)).Results;
var activities2 = (await this.UserFeed2.GetActivitiesAsync(0, 1)).Results;

Assert.IsNotNull(activities1);
Assert.AreEqual(1, activities1.Count());
Assert.AreEqual(response.Id, activities1.First().Id);

Assert.IsNotNull(activities2);
Assert.AreEqual(1, activities2.Count());
Assert.AreEqual(response.Id, activities2.First().Id);

// Use UnfollowMany with keepHistory=false
await Client.Batch.UnfollowManyAsync(new[]
{
new UnfollowRelation(UserFeed, FlatFeed, false),
new UnfollowRelation(UserFeed2, FlatFeed, false),
});

// Verify activities are removed
activities1 = (await this.UserFeed.GetActivitiesAsync(0, 1)).Results;
activities2 = (await this.UserFeed2.GetActivitiesAsync(0, 1)).Results;

Assert.IsNotNull(activities1);
Assert.AreEqual(0, activities1.Count());

Assert.IsNotNull(activities2);
Assert.AreEqual(0, activities2.Count());
}

[Test]
public async Task TestBatchUnfollowManyKeepHistoryTrue()
{
// First set up follows and add activities
await Client.Batch.FollowManyAsync(new[]
{
new Follow(UserFeed, FlatFeed),
new Follow(UserFeed2, FlatFeed),
});

var newActivity = new Activity("1", "test", "1");
var response = await this.FlatFeed.AddActivityAsync(newActivity);

// Verify follows are working
var activities1 = (await this.UserFeed.GetActivitiesAsync(0, 1)).Results;
var activities2 = (await this.UserFeed2.GetActivitiesAsync(0, 1)).Results;

Assert.IsNotNull(activities1);
Assert.AreEqual(1, activities1.Count());
Assert.AreEqual(response.Id, activities1.First().Id);

Assert.IsNotNull(activities2);
Assert.AreEqual(1, activities2.Count());
Assert.AreEqual(response.Id, activities2.First().Id);

// Use UnfollowMany with keepHistory=true
await Client.Batch.UnfollowManyAsync(new[]
{
new UnfollowRelation(UserFeed, FlatFeed, true),
new UnfollowRelation(UserFeed2, FlatFeed, true),
});

// Verify activities are retained
activities1 = (await this.UserFeed.GetActivitiesAsync(0, 1)).Results;
activities2 = (await this.UserFeed2.GetActivitiesAsync(0, 1)).Results;

Assert.IsNotNull(activities1);
Assert.AreEqual(1, activities1.Count());
Assert.AreEqual(response.Id, activities1.First().Id);

Assert.IsNotNull(activities2);
Assert.AreEqual(1, activities2.Count());
Assert.AreEqual(response.Id, activities2.First().Id);
}
}
}
7 changes: 7 additions & 0 deletions tests/ModerationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ public async Task TestFlagActivity()
newActivity.SetData<string>("stringint", "42");
newActivity.SetData<string>("stringdouble", "42.2");
newActivity.SetData<string>("stringcomplex", "{ \"test1\": 1, \"test2\": \"testing\" }");

// Set moderation data with origin_feed
var moderationData = new Dictionary<string, object>
{
{ "origin_feed", this.UserFeed.FeedId }
};
newActivity.SetData("moderation", moderationData);

var response = await this.UserFeed.AddActivityAsync(newActivity);
Assert.IsNotNull(response);
Expand Down
Loading