Skip to content

Commit 56afa90

Browse files
authored
feat(stats): add followstats (#108)
1 parent a927807 commit 56afa90

File tree

7 files changed

+138
-3
lines changed

7 files changed

+138
-3
lines changed

src/main/java/io/getstream/client/Client.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ CompletableFuture<Response> unfollow(FeedID source, FeedID target, RequestOption
317317
return stream.unfollow(token, source, target, options);
318318
}
319319

320+
CompletableFuture<Response> getFollowStats(
321+
FeedID feed, String[] followerSlugs, String[] followingSlugs) throws StreamException {
322+
final Token token = buildFollowToken(secret, TokenAction.READ);
323+
return stream.getFollowStats(token, feed, followerSlugs, followingSlugs);
324+
}
325+
320326
CompletableFuture<Response> updateActivityToTargets(
321327
FeedID feed, Activity activity, FeedID[] add, FeedID[] remove, FeedID[] newTargets)
322328
throws StreamException {

src/main/java/io/getstream/client/Feed.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
import static com.google.common.base.Preconditions.checkArgument;
44
import static com.google.common.base.Preconditions.checkNotNull;
55
import static io.getstream.core.utils.Serialization.*;
6+
import static io.getstream.core.utils.Serialization.deserializeContainer;
67

78
import com.google.common.collect.Iterables;
89
import io.getstream.core.exceptions.StreamException;
9-
import io.getstream.core.models.Activity;
10-
import io.getstream.core.models.FeedID;
11-
import io.getstream.core.models.FollowRelation;
10+
import io.getstream.core.models.*;
1211
import io.getstream.core.options.CustomQueryParameter;
1312
import io.getstream.core.options.Limit;
1413
import io.getstream.core.options.Offset;
@@ -330,6 +329,23 @@ public final CompletableFuture<Void> unfollow(
330329
});
331330
}
332331

332+
public final CompletableFuture<FollowStats> getFollowStats(
333+
Iterable<String> followerSlugs, Iterable<String> followingSlugs) throws StreamException {
334+
return client
335+
.getFollowStats(
336+
id,
337+
Iterables.toArray(followerSlugs, String.class),
338+
Iterables.toArray(followingSlugs, String.class))
339+
.thenApply(
340+
response -> {
341+
try {
342+
return deserializeContainerSingleItem(response, FollowStats.class);
343+
} catch (StreamException | IOException e) {
344+
throw new CompletionException(e);
345+
}
346+
});
347+
}
348+
333349
public final CompletableFuture<Void> updateActivityToTargets(
334350
Activity activity, Iterable<FeedID> add, Iterable<FeedID> remove) throws StreamException {
335351
return updateActivityToTargets(

src/main/java/io/getstream/core/Stream.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.net.MalformedURLException;
2121
import java.net.URISyntaxException;
2222
import java.net.URL;
23+
import java.util.ArrayList;
2324
import java.util.Date;
2425
import java.util.List;
2526
import java.util.Map;
@@ -372,6 +373,34 @@ public CompletableFuture<Response> unfollow(
372373
}
373374
}
374375

376+
public CompletableFuture<Response> getFollowStats(
377+
Token token,
378+
FeedID feed,
379+
String[] followerSlugs,
380+
String[] followingSlugs,
381+
RequestOption... options)
382+
throws StreamException {
383+
try {
384+
final URL url = followStatsPath(baseURL);
385+
final List<CustomQueryParameter> params = new ArrayList<>(4);
386+
final String feedId = String.join(":", feed.getSlug(), feed.getUserID());
387+
params.add(new CustomQueryParameter("followers", feedId));
388+
params.add(new CustomQueryParameter("following", feedId));
389+
390+
if (followerSlugs != null && followerSlugs.length > 0) {
391+
params.add(new CustomQueryParameter("followers_slugs", String.join(",", followerSlugs)));
392+
}
393+
if (followingSlugs != null && followingSlugs.length > 0) {
394+
params.add(new CustomQueryParameter("following_slugs", String.join(",", followingSlugs)));
395+
}
396+
397+
return httpClient.execute(
398+
buildGet(url, key, token, params.toArray(new CustomQueryParameter[0])));
399+
} catch (MalformedURLException | URISyntaxException e) {
400+
throw new StreamException(e);
401+
}
402+
}
403+
375404
public CompletableFuture<Response> updateActivityToTargets(
376405
Token token, FeedID feed, Activity activity, FeedID[] add, FeedID[] remove, FeedID[] replace)
377406
throws StreamException {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.getstream.core.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
6+
@JsonIgnoreProperties(ignoreUnknown = true)
7+
public final class FollowStats {
8+
@JsonProperty(value = "followers")
9+
private FollowStat followers;
10+
11+
@JsonProperty(value = "following")
12+
private FollowStat following;
13+
14+
public FollowStat getFollowers() {
15+
return followers;
16+
}
17+
18+
public FollowStat getFollowing() {
19+
return following;
20+
}
21+
22+
public class FollowStat {
23+
@JsonProperty(value = "count")
24+
private int count;
25+
26+
@JsonProperty(value = "feed")
27+
private String feed;
28+
29+
public int getCount() {
30+
return count;
31+
}
32+
33+
public String getFeed() {
34+
return feed;
35+
}
36+
}
37+
}

src/main/java/io/getstream/core/utils/Routes.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public final class Routes {
2525
private static final String reactionsPath = "reaction/";
2626
private static final String toTargetUpdatePath = "/activity_to_targets/";
2727
private static final String usersPath = "user/";
28+
private static final String followStatsPath = "stats/follow/";
2829

2930
private Routes() {
3031
/* nothing to see here */
@@ -112,6 +113,10 @@ public static URL buildUnfollowManyURL(URL baseURL) throws MalformedURLException
112113
return new URL(baseURL, basePath + unfollowManyPath);
113114
}
114115

116+
public static URL followStatsPath(URL baseURL) throws MalformedURLException {
117+
return new URL(baseURL, basePath + followStatsPath);
118+
}
119+
115120
private static URL buildSubdomainPath(URL baseURL, String subdomain, String apiPath, String path)
116121
throws MalformedURLException {
117122
try {

src/main/java/io/getstream/core/utils/Serialization.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ public static <T> List<T> deserializeContainer(
9090
throw deserializeException(response);
9191
}
9292

93+
public static <T> T deserializeContainerSingleItem(Response response, Class<T> element)
94+
throws IOException, StreamException {
95+
if (normalResponseCodes.contains(response.getCode())) {
96+
return fromJSON(
97+
response.getBody(), "results", mapper.getTypeFactory().constructType(element));
98+
}
99+
100+
throw deserializeException(response);
101+
}
102+
93103
public static <T> T deserializeContainer(Response response, String wrapper, JavaType element)
94104
throws IOException, StreamException {
95105
if (normalResponseCodes.contains(response.getCode())) {

src/test/java/io/getstream/client/FeedTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package io.getstream.client;
22

3+
import static org.junit.Assert.assertEquals;
4+
35
import com.google.common.collect.Lists;
46
import io.getstream.client.entities.FootballMatch;
57
import io.getstream.client.entities.Match;
68
import io.getstream.client.entities.VolleyballMatch;
79
import io.getstream.core.http.OKHTTPClientAdapter;
810
import io.getstream.core.models.Activity;
911
import io.getstream.core.models.FeedID;
12+
import io.getstream.core.models.FollowStats;
13+
import java.util.Collections;
1014
import java.util.Date;
1115
import java.util.List;
16+
import java.util.UUID;
1217
import okhttp3.OkHttpClient;
1318
import org.junit.Test;
1419

@@ -140,6 +145,33 @@ public void unfollow() throws Exception {
140145
feed1.unfollow(feed2).join();
141146
}
142147

148+
@Test
149+
public void getFollowStats() throws Exception {
150+
Client client =
151+
Client.builder(apiKey, secret)
152+
.httpClient(new OKHTTPClientAdapter(new OkHttpClient()))
153+
.build();
154+
String uuid1 = UUID.randomUUID().toString().replace("-", "");
155+
String uuid2 = UUID.randomUUID().toString().replace("-", "");
156+
String feed1Id = "flat:" + uuid1;
157+
FlatFeed feed1 = client.flatFeed("flat", uuid1);
158+
FlatFeed feed2 = client.flatFeed("flat", uuid2);
159+
feed1.follow(feed2).join();
160+
161+
FollowStats stats =
162+
feed1.getFollowStats(Collections.emptyList(), Lists.newArrayList("timeline")).join();
163+
assertEquals(0, stats.getFollowers().getCount());
164+
assertEquals(feed1Id, stats.getFollowers().getFeed());
165+
assertEquals(0, stats.getFollowing().getCount());
166+
assertEquals(feed1Id, stats.getFollowing().getFeed());
167+
168+
stats = feed1.getFollowStats(Collections.emptyList(), Lists.newArrayList("flat")).join();
169+
assertEquals(0, stats.getFollowers().getCount());
170+
assertEquals(feed1Id, stats.getFollowers().getFeed());
171+
assertEquals(1, stats.getFollowing().getCount());
172+
assertEquals(feed1Id, stats.getFollowing().getFeed());
173+
}
174+
143175
@Test
144176
public void updateActivityToTargets() throws Exception {
145177
Client client =

0 commit comments

Comments
 (0)