From bdb678ff20c961893b025ae66a0913012a083aec Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 31 Jul 2015 15:54:39 +0300 Subject: [PATCH 01/18] VKontakteProfile counters implementation --- .../social/vkontakte/api/Counters.java | 90 +++++++++++++++++++ .../vkontakte/api/VKontakteProfile.java | 9 ++ .../api/impl/json/CountersMixin.java | 38 ++++++++ .../api/impl/json/VKontakteModule.java | 2 + .../api/impl/json/VKontakteProfileMixin.java | 3 + .../vkontakte/api/impl/UsersTemplateTest.java | 1 + 6 files changed, 143 insertions(+) create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java new file mode 100644 index 0000000..f293b59 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.social.vkontakte.api; + +/** + * Counters. + * https://vk.com/dev/fields + * + * @author dIsoVi + */ +public class Counters { + private int albums; + private int videos; + private int audios; + private int notes; + private int photos; + private int groups; + private int gifts; + private int friends; + private int onlineFriends; + private int mutualFriends; + private int followers; + private int subscriptions; + private int pages; + + public int getAlbums() { + return albums; + } + + public int getVideos() { + return videos; + } + + public int getAudios() { + return audios; + } + + public int getNotes() { + return notes; + } + + public int getPhotos() { + return photos; + } + + public int getGroups() { + return groups; + } + + public int getGifts() { + return gifts; + } + + public int getFriends() { + return friends; + } + + public int getOnlineFriends() { + return onlineFriends; + } + + public int getMutualFriends() { + return mutualFriends; + } + + public int getFollowers() { + return followers; + } + + public int getSubscriptions() { + return subscriptions; + } + + public int getPages() { + return pages; + } +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java index c8edcab..d67a117 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java @@ -84,6 +84,15 @@ public class VKontakteProfile { private List relatives; private VKontakteProfile relationPartner; private LastSeen lastSeen; + private Counters counters; + + public Counters getCounters() { + return counters; + } + + public void setCounters(Counters counters) { + this.counters = counters; + } public String getDeactivated() { return deactivated; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java new file mode 100644 index 0000000..d9fe94e --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java @@ -0,0 +1,38 @@ +/* + * Copyright 2011-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.social.vkontakte.api.impl.json; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties +public class CountersMixin { + private int albums; + private int videos; + private int audios; + private int notes; + private int photos; + private int groups; + private int gifts; + private int friends; + @JsonProperty("online_friends") + private int onlineFriends; + @JsonProperty("mutual_friends") + private int mutualFriends; + private int followers; + private int subscriptions; + private int pages; +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java index 5a89dca..2afc128 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java @@ -20,6 +20,7 @@ import org.springframework.social.vkontakte.api.attachment.*; import org.springframework.social.vkontakte.api.attachment.Audio; import org.springframework.social.vkontakte.api.impl.json.attachment.*; +import org.w3c.dom.css.Counter; /** * Jackson module for setting up mixin annotations on VKontakte model types. @@ -71,6 +72,7 @@ public void setupModule(SetupContext context) { context.setMixInAnnotations(City.class, CityMixin.class); context.setMixInAnnotations(Country.class, CountryMixin.class); context.setMixInAnnotations(LastSeen.class, LastSeenMixin.class); + context.setMixInAnnotations(Counters.class, CountersMixin.class); context.setMixInAnnotations(Occupation.class, OccupationMixin.class); context.setMixInAnnotations(Personal.class, PersonalMixin.class); context.setMixInAnnotations(University.class, UniversityMixin.class); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java index f3c9b36..e76aa4a 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java @@ -155,6 +155,9 @@ class VKontakteProfileMixin { private VKontakteProfile relationPartner; @JsonProperty("last_seen") private LastSeen lastSeen; + @JsonProperty("counters") + private Counters counters; + static class VKGenderDeserializer extends JsonDeserializer { @Override diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index d30a91c..e59287c 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -48,6 +48,7 @@ public void getUser_currentUser() { assertEquals(1, profile.getId()); assertEquals("Павел", profile.getFirstName()); assertEquals("Дуров", profile.getLastName()); + assertEquals(705, profile.getCounters().getFriends()); } @Test From e5aef3349260f79c51789989158e47502621d4f7 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 31 Jul 2015 16:02:07 +0300 Subject: [PATCH 02/18] IUsersOperations.getUsers screen_name support (#37 resolved) --- .../social/vkontakte/api/IUsersOperations.java | 4 ++-- .../social/vkontakte/api/impl/UsersTemplate.java | 6 +++--- .../social/vkontakte/api/impl/UsersTemplateTest.java | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java index 9680c30..930d92d 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java @@ -51,7 +51,7 @@ public interface IUsersOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - List getUsers(List userIds); + List getUsers(List userIds); /** * Retrieves profiles for specified user unique identifiers. @@ -63,5 +63,5 @@ public interface IUsersOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - List getUsers(List userIds, String fields); + List getUsers(List userIds, String fields); } \ No newline at end of file diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java index 8f7b8fe..3b0f4d6 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java @@ -39,13 +39,13 @@ public UsersTemplate(RestTemplate restTemplate, String accessToken, ObjectMapper this.restTemplate = restTemplate; } - public List getUsers(List userIds, String fields) { + public List getUsers(List userIds, String fields) { requireAuthorization(); Properties props = new Properties(); StringBuilder uids = new StringBuilder(); if(userIds != null) { - for(Long uid : userIds) { + for(String uid : userIds) { if(uids.toString().isEmpty()) uids.append(uid); else uids.append(",").append(uid); @@ -64,7 +64,7 @@ public List getUsers(List userIds, String fields) { return profiles.getProfiles(); } - public List getUsers(List userIds) { + public List getUsers(List userIds) { return getUsers(userIds, null); } diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index e59287c..37fc3fb 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -54,9 +54,9 @@ public void getUser_currentUser() { @Test public void getUsers_currentUser() { mockServer - .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name&user_ids=1%2C2183%2C77478")) + .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name&user_ids=durov%2C2183%2C77478")) .andExpect(method(GET)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); - Long[] userIds = {1L, 2183L, 77478L}; + String[] userIds = {"durov", "2183", "77478"}; List profiles = vkontakte.usersOperations().getUsers(Arrays.asList(userIds)); assertProfiles(profiles); @@ -69,7 +69,7 @@ public void getUser_unauthorized() { @Test(expected = MissingAuthorizationException.class) public void getUsers_unauthorized() { - Long[] userIds = {1L, 2L}; + String[] userIds = {"1", "2"}; unauthorizedVKontakte.usersOperations().getUsers(Arrays.asList(userIds)); } @@ -87,7 +87,7 @@ public void getUsers_expiredToken() { mockServer .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name&user_ids=1%2C2")) .andExpect(method(GET)).andRespond(withSuccess(jsonResource("error-code-5"), APPLICATION_JSON)); - Long[] userIds = {1L, 2L}; + String[] userIds = {"1", "2"}; vkontakte.usersOperations().getUsers(Arrays.asList(userIds)); } From 323eb29ea9b8b839cd89b68b123fd4511b2fb2d0 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 31 Jul 2015 16:37:34 +0300 Subject: [PATCH 03/18] IFriendsOperations.get with empty fields implementation (#38 resolved) --- .../social/vkontakte/api/VKontakteProfile.java | 6 ++++++ .../social/vkontakte/api/impl/FriendsTemplate.java | 5 ++++- .../social/vkontakte/api/impl/FriendsTemplateTest.java | 10 +++++++++- .../vkontakte/api/impl/friends-get-without-fields.json | 10 ++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java index d67a117..4d33a87 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java @@ -23,6 +23,12 @@ * @author vkolodrevskiy */ public class VKontakteProfile { + public VKontakteProfile(long id) { + this.id = id; + } + + public VKontakteProfile() { + } private final static String PROFILE_URL_EXTESTION = "http://vk.com/"; private long id; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java index 7ad30cb..61081f3 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.social.vkontakte.api.*; +import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; import java.net.URI; @@ -67,7 +68,9 @@ public List get(Long userId, String fields, int count, int off if (offset != -1) { props.put("offset", offset); } - props.put("fields", fields); + if (!StringUtils.isEmpty(fields)) { + props.put("fields", fields); + } URI uri = makeOperationURL("friends.get", props, ApiVersion.VERSION_5_27); VKGenericResponse response = restTemplate.getForObject(uri, VKGenericResponse.class); diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java index 6b88af6..8413d5e 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java @@ -45,7 +45,15 @@ public void get_currentUser() throws ParseException { assertFriends(friends); } - @Test(expected = MissingAuthorizationException.class) + @Test + public void getFriendsWithoutFields() throws Exception { + mockServer.expect(requestTo("https://api.vk.com/method/friends.get?access_token=ACCESS_TOKEN&v=5.27")) + .andExpect(method(GET)) + .andRespond(withSuccess(jsonResource("friends-get-without-fields"), APPLICATION_JSON)); + List friends = vkontakte.friendsOperations().get(""); + } + + @Test(expected = MissingAuthorizationException.class) public void get_currentUser_unauthorized() { unauthorizedVKontakte.friendsOperations().get(); } diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json new file mode 100644 index 0000000..73a4296 --- /dev/null +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json @@ -0,0 +1,10 @@ +{ + "response": { + "count": 718, + "items": [ + 184760, + 3271875, + 680751 + ] + } +} \ No newline at end of file From a7c25e87f738cebbd11c977692988d57664b1c31 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 31 Jul 2015 16:58:58 +0300 Subject: [PATCH 04/18] IFriendsOperations returns VKArray instead of List (so we can get total count of friends) --- .../vkontakte/api/IFriendsOperations.java | 18 ++++++++++-------- .../vkontakte/api/impl/FriendsTemplate.java | 13 +++++++------ .../api/impl/FriendsTemplateTest.java | 16 +++++++++++----- ...on => friends-get-without-fields-5_35.json} | 0 4 files changed, 28 insertions(+), 19 deletions(-) rename spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/{friends-get-without-fields.json => friends-get-without-fields-5_35.json} (100%) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java index a42cc76..9afeb6e 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java @@ -15,6 +15,8 @@ */ package org.springframework.social.vkontakte.api; +import org.springframework.social.vkontakte.api.impl.json.VKArray; + import java.util.List; /** @@ -22,7 +24,7 @@ * @author vkolodrevskiy */ public interface IFriendsOperations { - public final static String DEFAULT_FIELDS = "first_name,last_name,photo_50,photo_100,photo_200,contacts,bdate,sex,screen_name"; + String DEFAULT_FIELDS = "first_name,last_name,photo_50,photo_100,photo_200,contacts,bdate,sex,screen_name"; /** * Retrieves a list of user friends for the current authorized user. * @return a list of user friends profiles. @@ -30,7 +32,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List get(); + VKArray get(); /** * Retrieves a list of user friends for the current authorized user. @@ -40,7 +42,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List get(String fields); + VKArray get(String fields); /** * Retrieves a list of user friends for specified user unique identifier. @@ -50,7 +52,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List get(Long userId); + VKArray get(Long userId); /** * Retrieves a list of user friends for specified user unique identifier. @@ -61,7 +63,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List get(Long userId, String fields); + VKArray get(Long userId, String fields); /** * Retrieves a list of user friends for specified user unique identifier. @@ -74,7 +76,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List get(Long userId, String fields, int count, int offset); + VKArray get(Long userId, String fields, int count, int offset); /** * Retrieves a list of user friends id's that are online for the current authorized user. @@ -88,7 +90,7 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List> getOnline(boolean onlineMobile, int count, int offset); + List> getOnline(boolean onlineMobile, int count, int offset); /** * Retrieves a list of user friends that are online for specified user unique identifier. @@ -103,5 +105,5 @@ public interface IFriendsOperations { * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - public List> getOnline(Long userId, boolean onlineMobile, int count, int offset); + List> getOnline(Long userId, boolean onlineMobile, int count, int offset); } \ No newline at end of file diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java index 61081f3..eb81973 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.social.vkontakte.api.*; +import org.springframework.social.vkontakte.api.impl.json.VKArray; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; @@ -39,23 +40,23 @@ public FriendsTemplate(RestTemplate restTemplate, String accessToken, ObjectMapp this.restTemplate = restTemplate; } - public List get(String fields) { + public VKArray get(String fields) { return get(null, fields); } - public List get() { + public VKArray get() { return get(null, IFriendsOperations.DEFAULT_FIELDS); } - public List get(Long userId) { + public VKArray get(Long userId) { return get(userId, IFriendsOperations.DEFAULT_FIELDS); } - public List get(Long userId, String fields) { + public VKArray get(Long userId, String fields) { return get(userId, fields, -1, -1); } - public List get(Long userId, String fields, int count, int offset) { + public VKArray get(Long userId, String fields, int count, int offset) { requireAuthorization(); Properties props = new Properties(); @@ -76,7 +77,7 @@ public List get(Long userId, String fields, int count, int off VKGenericResponse response = restTemplate.getForObject(uri, VKGenericResponse.class); checkForError(response); - return deserializeVK50ItemsResponse(response, VKontakteProfile.class).getItems(); + return deserializeVK50ItemsResponse(response, VKontakteProfile.class); } public List> getOnline(boolean onlineMobile, int count, int offset) { diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java index 8413d5e..2c3bb7d 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/FriendsTemplateTest.java @@ -19,6 +19,7 @@ import org.springframework.social.MissingAuthorizationException; import org.springframework.social.vkontakte.api.VKontakteErrorException; import org.springframework.social.vkontakte.api.VKontakteProfile; +import org.springframework.social.vkontakte.api.impl.json.VKArray; import java.text.ParseException; import java.util.List; @@ -41,7 +42,7 @@ public void get_currentUser() throws ParseException { .andExpect(method(GET)) .andRespond(withSuccess(jsonResource("list-of-friends-5_27"), APPLICATION_JSON)); - List friends = vkontakte.friendsOperations().get(); + VKArray friends = vkontakte.friendsOperations().get(); assertFriends(friends); } @@ -49,8 +50,11 @@ public void get_currentUser() throws ParseException { public void getFriendsWithoutFields() throws Exception { mockServer.expect(requestTo("https://api.vk.com/method/friends.get?access_token=ACCESS_TOKEN&v=5.27")) .andExpect(method(GET)) - .andRespond(withSuccess(jsonResource("friends-get-without-fields"), APPLICATION_JSON)); - List friends = vkontakte.friendsOperations().get(""); + .andRespond(withSuccess(jsonResource("friends-get-without-fields-5_35"), APPLICATION_JSON)); + VKArray friends = vkontakte.friendsOperations().get(""); + assertEquals(184760, friends.getItems().get(0).getId()); + assertEquals(3, friends.getItems().size()); + assertEquals(718, friends.getCount()); } @Test(expected = MissingAuthorizationException.class) @@ -64,7 +68,7 @@ public void get_byUserId() throws ParseException { .andExpect(method(GET)) .andRespond(withSuccess(jsonResource("list-of-friends-5_27"), APPLICATION_JSON)); - List friends = vkontakte.friendsOperations().get(1L); + VKArray friends = vkontakte.friendsOperations().get(1L); assertFriends(friends); } @@ -140,7 +144,9 @@ public void getOnlineAllParametersPresent() { vkontakte.friendsOperations().getOnline(123L, true, 5, 6); } - private void assertFriends(List profiles) throws ParseException { + private void assertFriends(VKArray profilesArray) throws ParseException { + List profiles = profilesArray.getItems(); + assertEquals(705, profilesArray.getCount()); assertEquals(5, profiles.size()); assertEquals(15439101, profiles.get(0).getId()); } diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields-5_35.json similarity index 100% rename from spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields.json rename to spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/friends-get-without-fields-5_35.json From 4fd0b5c66c05ac6d692255b11abc3e26b7678b5d Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 31 Jul 2015 20:11:50 +0300 Subject: [PATCH 05/18] IUsersOperations.getUsers is using POST request now (this fixes problem when lots of users are requested) --- .../social/vkontakte/api/IUsersOperations.java | 2 +- .../api/impl/AbstractVKontakteOperations.java | 8 ++++++++ .../vkontakte/api/impl/UsersTemplate.java | 14 +++++++------- .../vkontakte/api/impl/UsersTemplateTest.java | 17 +++++++++-------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java index 930d92d..b265f27 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java @@ -22,7 +22,7 @@ * @author vkolodrevskiy */ public interface IUsersOperations { - public final static String DEFAULT_FIELDS = "first_name,last_name,photo_50,photo_100,photo_200,contacts,bdate,sex,screen_name"; + String DEFAULT_FIELDS = "first_name,last_name,photo_50,photo_100,photo_200,contacts,bdate,sex,screen_name"; /** * Retrieves the profile for the authenticated user. * @return the user's profile information. diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java index 4c3e3d7..3c976ae 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java @@ -26,6 +26,7 @@ import org.springframework.social.vkontakte.api.VKontakteErrorException; import org.springframework.social.vkontakte.api.impl.json.VKArray; import org.springframework.util.Assert; +import org.springframework.util.MultiValueMap; import java.net.URI; import java.util.ArrayList; @@ -74,6 +75,13 @@ protected URI makeOperationURL(String method, Properties params, ApiVersion apiV return uri.build(); } + protected URI makeOperationPOST(String method, MultiValueMap data, ApiVersion apiVersion) { + URIBuilder uri = URIBuilder.fromUri(VK_REST_URL + method); + data.set("access_token", accessToken); + data.set("v", apiVersion.toString()); + return uri.build(); + } + protected void preProcessURI(URIBuilder uri) { // add access_token // TODO: for some methods we do not need access token, so think about it. diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java index 3b0f4d6..3cc582e 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java @@ -20,6 +20,8 @@ import org.springframework.social.vkontakte.api.IUsersOperations; import org.springframework.social.vkontakte.api.VKontakteProfile; import org.springframework.social.vkontakte.api.VKontakteProfiles; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.net.URI; @@ -41,7 +43,7 @@ public UsersTemplate(RestTemplate restTemplate, String accessToken, ObjectMapper public List getUsers(List userIds, String fields) { requireAuthorization(); - Properties props = new Properties(); + MultiValueMap data = new LinkedMultiValueMap(); StringBuilder uids = new StringBuilder(); if(userIds != null) { @@ -50,15 +52,13 @@ public List getUsers(List userIds, String fields) { uids.append(uid); else uids.append(",").append(uid); } - props.put("user_ids", uids.toString()); + data.set("user_ids", uids.toString()); } - - props.put("fields", fields != null? fields: IUsersOperations.DEFAULT_FIELDS); + data.set("fields", fields != null? fields: IUsersOperations.DEFAULT_FIELDS); // see documentation under http://vk.com/dev/users.get - URI uri = makeOperationURL("users.get", props, ApiVersion.VERSION_5_27); - - VKontakteProfiles profiles = restTemplate.getForObject(uri, VKontakteProfiles.class); + URI uri = makeOperationPOST("users.get", data, ApiVersion.VERSION_5_27); + VKontakteProfiles profiles = restTemplate.postForObject(uri, data, VKontakteProfiles.class); checkForError(profiles); return profiles.getProfiles(); diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index 37fc3fb..cae122b 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; @@ -40,8 +41,8 @@ public class UsersTemplateTest extends AbstractVKontakteApiTest { @Test public void getUser_currentUser() { mockServer - .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=sex%2C+bdate%2C+city%2C+country%2C+photo_50%2C+photo_100%2C+photo_200_orig%2C+photo_200%2C+photo_400_orig%2C+photo_max%2C+photo_max_orig%2C+photo_id%2C+online%2C+online_mobile%2C+domain%2C+has_mobile%2C+contacts%2C+connections%2C+site%2C+education%2C+universities%2C+schools%2C+can_post%2C+can_see_all_posts%2C+can_see_audio%2C+can_write_private_message%2C+status%2C+last_seen%2C+common_count%2C+relation%2C+relatives%2C+counters%2C+screen_name%2C+maiden_name%2C+timezone%2C+occupation%2Cactivities%2C+interests%2C+music%2C+movies%2C+tv%2C+books%2C+games%2C+about%2C+quotes%2C+personal%2C+friends_status")) - .andExpect(method(GET)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); + .expect(requestTo("https://api.vk.com/method/users.get")) + .andExpect(method(POST)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); VKontakteProfile profile = vkontakte.usersOperations().getUser("sex, bdate, city, country, photo_50, photo_100, photo_200_orig, photo_200, photo_400_orig, photo_max, photo_max_orig, photo_id, online, online_mobile, domain, has_mobile, contacts, connections, site, education, universities, schools, can_post, can_see_all_posts, can_see_audio, can_write_private_message, status, last_seen, common_count, relation, relatives, counters, screen_name, maiden_name, timezone, occupation,activities, interests, music, movies, tv, books, games, about, quotes, personal, friends_status"); @@ -54,8 +55,8 @@ public void getUser_currentUser() { @Test public void getUsers_currentUser() { mockServer - .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name&user_ids=durov%2C2183%2C77478")) - .andExpect(method(GET)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); + .expect(requestTo("https://api.vk.com/method/users.get")) + .andExpect(method(POST)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); String[] userIds = {"durov", "2183", "77478"}; List profiles = vkontakte.usersOperations().getUsers(Arrays.asList(userIds)); @@ -76,8 +77,8 @@ public void getUsers_unauthorized() { @Test(expected = VKontakteErrorException.class) public void getUser_expiredToken() { mockServer - .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name")) - .andExpect(method(GET)).andRespond(withSuccess(jsonResource("error-code-5"), APPLICATION_JSON)); + .expect(requestTo("https://api.vk.com/method/users.get")) + .andExpect(method(POST)).andRespond(withSuccess(jsonResource("error-code-5"), APPLICATION_JSON)); vkontakte.usersOperations().getUser(); } @@ -85,8 +86,8 @@ public void getUser_expiredToken() { @Test(expected = VKontakteErrorException.class) public void getUsers_expiredToken() { mockServer - .expect(requestTo("https://api.vk.com/method/users.get?access_token=ACCESS_TOKEN&v=5.27&fields=first_name%2Clast_name%2Cphoto_50%2Cphoto_100%2Cphoto_200%2Ccontacts%2Cbdate%2Csex%2Cscreen_name&user_ids=1%2C2")) - .andExpect(method(GET)).andRespond(withSuccess(jsonResource("error-code-5"), APPLICATION_JSON)); + .expect(requestTo("https://api.vk.com/method/users.get")) + .andExpect(method(POST)).andRespond(withSuccess(jsonResource("error-code-5"), APPLICATION_JSON)); String[] userIds = {"1", "2"}; vkontakte.usersOperations().getUsers(Arrays.asList(userIds)); } From 17a1a3e5351f7925d2fafbd44efc6d1f41cd8252 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Mon, 3 Aug 2015 11:40:36 +0300 Subject: [PATCH 06/18] minor import fixes --- .../social/vkontakte/api/impl/json/CountersMixin.java | 2 -- .../social/vkontakte/api/impl/json/VKontakteModule.java | 1 - 2 files changed, 3 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java index d9fe94e..9addb9c 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java @@ -15,10 +15,8 @@ */ package org.springframework.social.vkontakte.api.impl.json; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -@JsonIgnoreProperties public class CountersMixin { private int albums; private int videos; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java index 2afc128..241ce39 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java @@ -20,7 +20,6 @@ import org.springframework.social.vkontakte.api.attachment.*; import org.springframework.social.vkontakte.api.attachment.Audio; import org.springframework.social.vkontakte.api.impl.json.attachment.*; -import org.w3c.dom.css.Counter; /** * Jackson module for setting up mixin annotations on VKontakte model types. From 11978986bcf97241f60eb03c6ed66f9ae1ef59f7 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Mon, 3 Aug 2015 17:48:32 +0300 Subject: [PATCH 07/18] support for order and name case params for IFriendsOperations and IUsersOperations --- .../vkontakte/api/IFriendsOperations.java | 17 +++++++++++ .../vkontakte/api/IUsersOperations.java | 15 ++++++++++ .../vkontakte/api/VKontakteProfile.java | 3 ++ .../vkontakte/api/impl/FriendsTemplate.java | 13 ++++++++ .../vkontakte/api/impl/UsersTemplate.java | 30 ++++++++++++------- .../vkontakte/api/vkenums/FriendsOrder.java | 29 ++++++++++++++++++ .../vkontakte/api/vkenums/NameCase.java | 30 +++++++++++++++++++ 7 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/FriendsOrder.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/NameCase.java diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java index 9afeb6e..6e788ab 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IFriendsOperations.java @@ -16,6 +16,8 @@ package org.springframework.social.vkontakte.api; import org.springframework.social.vkontakte.api.impl.json.VKArray; +import org.springframework.social.vkontakte.api.vkenums.FriendsOrder; +import org.springframework.social.vkontakte.api.vkenums.NameCase; import java.util.List; @@ -78,6 +80,21 @@ public interface IFriendsOperations { */ VKArray get(Long userId, String fields, int count, int offset); + /** + * Retrieves a list of user friends for specified user unique identifier. + * @param userId user unique identifier for which to get friends. + * @param fields VKontakte fields to retrieve, comma-delimited. + * @param order sort order. + * @param nameCase case for declension of user name and surname. + * @param count Number(positive number) of friends to return. If you want to return all friends pass negative number. + * @param offset Offset(positive number) needed to return a specific subset of friends. + * @return a list of user friends profiles. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. + */ + VKArray get(Long userId, String fields, FriendsOrder order, NameCase nameCase, int count, int offset); + /** * Retrieves a list of user friends id's that are online for the current authorized user. * Result List will contain 2 lists if you set onlineMobile parameter to true. diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java index b265f27..b0641f9 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java @@ -15,6 +15,8 @@ */ package org.springframework.social.vkontakte.api; +import org.springframework.social.vkontakte.api.vkenums.NameCase; + import java.util.List; /** @@ -64,4 +66,17 @@ public interface IUsersOperations { * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ List getUsers(List userIds, String fields); + + /** + * Retrieves profiles for specified user unique identifiers. + * @param userIds VKontakte user profile unique identifiers, for which to gt data. + * @param fields VKontakte fields to retrieve, comma-delimited. + * If null is passed user profile or the current user will be returned. + * @param nameCase case for declension of user name and surname. + * @return the user's profile information. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. + */ + List getUsers(List userIds, String fields, NameCase nameCase); } \ No newline at end of file diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java index 4d33a87..bab98c4 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java @@ -566,6 +566,9 @@ public void setQuotes(String quotes) { } public String getProfileURL() { + if (screenName == null) { + return PROFILE_URL_EXTESTION + "id" + id; + } return PROFILE_URL_EXTESTION + screenName; } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java index eb81973..fdd92a2 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.social.vkontakte.api.*; import org.springframework.social.vkontakte.api.impl.json.VKArray; +import org.springframework.social.vkontakte.api.vkenums.FriendsOrder; +import org.springframework.social.vkontakte.api.vkenums.NameCase; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; @@ -57,6 +59,10 @@ public VKArray get(Long userId, String fields) { } public VKArray get(Long userId, String fields, int count, int offset) { + return get(userId, fields, FriendsOrder.NONE, NameCase.nom, count, offset); + } + + public VKArray get(Long userId, String fields, FriendsOrder order, NameCase nameCase, int count, int offset) { requireAuthorization(); Properties props = new Properties(); @@ -72,6 +78,13 @@ public VKArray get(Long userId, String fields, int count, int if (!StringUtils.isEmpty(fields)) { props.put("fields", fields); } + if (order != FriendsOrder.NONE) { + props.put("order", order); + } + if (nameCase != NameCase.nom) { + props.put("name_case", nameCase); + } + URI uri = makeOperationURL("friends.get", props, ApiVersion.VERSION_5_27); VKGenericResponse response = restTemplate.getForObject(uri, VKGenericResponse.class); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java index 3cc582e..a3cb1da 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java @@ -20,6 +20,7 @@ import org.springframework.social.vkontakte.api.IUsersOperations; import org.springframework.social.vkontakte.api.VKontakteProfile; import org.springframework.social.vkontakte.api.VKontakteProfiles; +import org.springframework.social.vkontakte.api.vkenums.NameCase; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; @@ -41,19 +42,30 @@ public UsersTemplate(RestTemplate restTemplate, String accessToken, ObjectMapper this.restTemplate = restTemplate; } + public List getUsers(List userIds) { + return getUsers(userIds, null); + } + public List getUsers(List userIds, String fields) { + return getUsers(userIds, fields, NameCase.nom); + } + + public List getUsers(List userIds, String fields, NameCase nameCase) { requireAuthorization(); MultiValueMap data = new LinkedMultiValueMap(); - StringBuilder uids = new StringBuilder(); - if(userIds != null) { - for(String uid : userIds) { - if(uids.toString().isEmpty()) - uids.append(uid); - else uids.append(",").append(uid); + if (userIds != null) { + StringBuilder sb = new StringBuilder(); + for(String uid : userIds){ + sb.append(uid).append(","); } - data.set("user_ids", uids.toString()); + sb.deleteCharAt(sb.length() - 1); + data.set("user_ids", sb.toString()); } + if (nameCase != NameCase.nom) { + data.set("name_case", nameCase); + } + data.set("fields", fields != null? fields: IUsersOperations.DEFAULT_FIELDS); // see documentation under http://vk.com/dev/users.get @@ -64,10 +76,6 @@ public List getUsers(List userIds, String fields) { return profiles.getProfiles(); } - public List getUsers(List userIds) { - return getUsers(userIds, null); - } - public VKontakteProfile getUser() { return getUsers(null).get(0); } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/FriendsOrder.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/FriendsOrder.java new file mode 100644 index 0000000..fad570d --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/FriendsOrder.java @@ -0,0 +1,29 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.social.vkontakte.api.vkenums; + +/** + * Defines sort order for friends.get operation + * API.version = 5.35 + * @author dIsoVi + */ +public enum FriendsOrder { + NONE, + hints, + random, + mobile, + name +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/NameCase.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/NameCase.java new file mode 100644 index 0000000..041f1f9 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/NameCase.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.social.vkontakte.api.vkenums; + +/** + * Case for declension of user name and surname + * API.version = 5.35 + * @author dIsoVi + */ +public enum NameCase { + nom, // default + gen, + dat, + acc, + ins, + abl +} From 1fcb6421459f78994fa4753c02b941d5d2fac354 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Tue, 4 Aug 2015 11:17:26 +0300 Subject: [PATCH 08/18] updated Counters for latest API (resolved #41) --- .../springframework/social/vkontakte/api/Counters.java | 10 ++++++++++ .../social/vkontakte/api/impl/json/CountersMixin.java | 6 ++++++ .../social/vkontakte/api/impl/UsersTemplateTest.java | 1 + .../vkontakte/api/impl/list-of-profiles-5_27.json | 4 ++++ 4 files changed, 21 insertions(+) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java index f293b59..d1c4deb 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Counters.java @@ -32,10 +32,20 @@ public class Counters { private int friends; private int onlineFriends; private int mutualFriends; + private int userPhotos; + private int userVideos; private int followers; private int subscriptions; private int pages; + public int getUserVideos() { + return userVideos; + } + + public int getUserPhotos() { + return userPhotos; + } + public int getAlbums() { return albums; } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java index 9addb9c..4bc6046 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CountersMixin.java @@ -15,8 +15,10 @@ */ package org.springframework.social.vkontakte.api.impl.json; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +@JsonIgnoreProperties(ignoreUnknown = true) public class CountersMixin { private int albums; private int videos; @@ -30,6 +32,10 @@ public class CountersMixin { private int onlineFriends; @JsonProperty("mutual_friends") private int mutualFriends; + @JsonProperty("user_photos") + private int userPhotos; + @JsonProperty("user_videos") + private int userVideos; private int followers; private int subscriptions; private int pages; diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index cae122b..1b5be1e 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -50,6 +50,7 @@ public void getUser_currentUser() { assertEquals("Павел", profile.getFirstName()); assertEquals("Дуров", profile.getLastName()); assertEquals(705, profile.getCounters().getFriends()); + assertEquals(12, profile.getCounters().getUserPhotos()); } @Test diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/list-of-profiles-5_27.json b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/list-of-profiles-5_27.json index 3e8a12b..e06f53e 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/list-of-profiles-5_27.json +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/list-of-profiles-5_27.json @@ -45,9 +45,13 @@ "audios": 0, "notes": 6, "photos": 188, + "groups": 123, + "gifts": 11, "friends": 705, "online_friends": 131, "mutual_friends": 1, + "user_photos": 12, + "user_videos": 1, "followers": 6155681, "subscriptions": 0, "pages": 37 From 850aef332be9203f358236d577dc4cb3a6256c88 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Wed, 5 Aug 2015 19:18:45 +0300 Subject: [PATCH 09/18] basic execute implementation --- .../vkontakte/api/IUtilsOperations.java | 15 +- .../vkontakte/api/impl/UtilsTemplate.java | 16 +- .../vkontakte/api/impl/VKontakteTemplate.java | 2 +- .../vkontakte/api/impl/UtilsTemplateTest.java | 36 ++- .../api/impl/utils-execute-response-5_35.json | 240 ++++++++++++++++++ 5 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/utils-execute-response-5_35.json diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUtilsOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUtilsOperations.java index e0fa040..a37d123 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUtilsOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUtilsOperations.java @@ -20,5 +20,18 @@ * @author dIsoVi */ public interface IUtilsOperations { - public VKObject resolveScreenName(String screenName); + /** + * utils.resolveScreenName + * Detects a type of object (e.g., user, community, application) and its ID by screen name. + * @param screenName Screen name of the user, community (e.g., apiclub, andrew, or rules_of_war), or application. + * @return an object with type and id + */ + VKObject resolveScreenName(String screenName); + + /** + * A universal method for calling a sequence of other methods while saving and filtering interim results. + * @param code - Algorithm code in VKScript (https://vk.com/dev/execute) + * @return data requested by the algorithm + */ + VKGenericResponse execute(String code); } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UtilsTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UtilsTemplate.java index b8e3ba4..f4b459d 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UtilsTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UtilsTemplate.java @@ -5,6 +5,8 @@ import org.springframework.social.vkontakte.api.IUtilsOperations; import org.springframework.social.vkontakte.api.VKGenericResponse; import org.springframework.social.vkontakte.api.VKObject; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.net.URI; @@ -17,8 +19,8 @@ public class UtilsTemplate extends AbstractVKontakteOperations implements IUtilsOperations { private final RestTemplate restTemplate; - public UtilsTemplate(RestTemplate restTemplate, ObjectMapper objectMapper) { - super(false, null, objectMapper); + public UtilsTemplate(RestTemplate restTemplate, String accessToken, ObjectMapper objectMapper, boolean isAuthorizedForUser) { + super(isAuthorizedForUser, accessToken, objectMapper); this.restTemplate = restTemplate; } @@ -29,4 +31,14 @@ public VKObject resolveScreenName(String screenName) { VKGenericResponse response = restTemplate.getForObject(uri, VKGenericResponse.class); return deserializeVK50Item(response, VKObject.class); } + + // TODO: give user the ability to deserialize response by setting template class? + public VKGenericResponse execute(String code) { + MultiValueMap data = new LinkedMultiValueMap(); + data.set("code", code); + URI uri = makeOperationPOST("execute", data, ApiVersion.VERSION_5_27); + VKGenericResponse response = restTemplate.postForObject(uri, data, VKGenericResponse.class); + checkForError(response); + return response; + } } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/VKontakteTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/VKontakteTemplate.java index 4403791..6807c82 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/VKontakteTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/VKontakteTemplate.java @@ -103,7 +103,7 @@ private void initSubApis() { audioOperations = new AudioTemplate(getRestTemplate(), accessToken, objectMapper, isAuthorized()); groupsOperations = new GroupsTemplate(getRestTemplate(), accessToken, objectMapper, isAuthorized()); newsFeedOperations = new NewsFeedTemplate(getRestTemplate(), accessToken, objectMapper, isAuthorized()); - utilsOperations = new UtilsTemplate(getRestTemplate(), objectMapper); + utilsOperations = new UtilsTemplate(getRestTemplate(), accessToken, objectMapper, isAuthorized()); } public IUsersOperations usersOperations() { diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java index 4dae470..f44f1ad 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java @@ -15,11 +15,15 @@ */ package org.springframework.social.vkontakte.api.impl; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import org.junit.Test; +import org.springframework.social.vkontakte.api.VKGenericResponse; import org.springframework.social.vkontakte.api.VKObject; import static org.junit.Assert.assertEquals; import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; @@ -32,7 +36,7 @@ public class UtilsTemplateTest extends AbstractVKontakteApiTest { @Test public void resolveScreenName() { - mockServer.expect(requestTo("https://api.vk.com/method/utils.resolveScreenName?access_token=&v=5.27&screen_name=durov")) + mockServer.expect(requestTo("https://api.vk.com/method/utils.resolveScreenName?access_token=ACCESS_TOKEN&v=5.27&screen_name=durov")) .andExpect(method(GET)) .andRespond(withSuccess(jsonResource("utils-resolve-screen-name-5.27"), APPLICATION_JSON)); VKObject vkObject = vkontakte.utilsOperations().resolveScreenName("durov"); @@ -42,10 +46,38 @@ public void resolveScreenName() { @Test public void resolveScreenNameEmpty() { - mockServer.expect(requestTo("https://api.vk.com/method/utils.resolveScreenName?access_token=&v=5.27&screen_name=durov")) + mockServer.expect(requestTo("https://api.vk.com/method/utils.resolveScreenName?access_token=ACCESS_TOKEN&v=5.27&screen_name=durov")) .andExpect(method(GET)) .andRespond(withSuccess(jsonResource("utils-resolve-screen-name-empty-5.27"), APPLICATION_JSON)); VKObject vkObject = vkontakte.utilsOperations().resolveScreenName("durov"); assertEquals(null, vkObject); } + + @Test + public void testExecute() throws Exception { + mockServer.expect(requestTo("https://api.vk.com/method/execute")) + .andExpect(method(POST)) + .andRespond(withSuccess(jsonResource("utils-execute-response-5_35"), APPLICATION_JSON)); + String code = "var posts = API.wall.get({\"count\": 1});\n" + + "\n" + + "if (posts.count<0) {\n" + + " return {\"post\": null, \"copy_owner\": null};\n" + + "} else {\n" + + " var post = posts.items[0];\n" + + " var copy_owner=null;\n" + + " if (post.copy_history[0]){\n" + + " if (post.copy_history[0].owner_id > 0) {\n" + + " copy_owner = API.users.get({\"user_id\": post.copy_history[0].owner_id})[0];\n" + + " } else\n" + + " if (post.copy_history[0].owner_id < 0) {\n" + + " copy_owner = API.groups.getById({\"group_ids\": -post.copy_history[0].owner_id})[0];\n" + + " }\n" + + " return {\"post\": post, \"copy_owner\": copy_owner};\n" + + " } else {\n" + + " return {\"post\": post, \"copy_owner\": null};\n" + + " }\n" + + "}"; + VKGenericResponse response = vkontakte.utilsOperations().execute(code); + assertEquals(1, response.getResponse().get("post").get("copy_history").size()); + } } diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/utils-execute-response-5_35.json b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/utils-execute-response-5_35.json new file mode 100644 index 0000000..fec87a5 --- /dev/null +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/utils-execute-response-5_35.json @@ -0,0 +1,240 @@ +{ + "response": { + "post": { + "id": 175, + "from_id": 16051904, + "owner_id": 16051904, + "date": 1438767744, + "post_type": "post", + "text": "", + "copy_history": [ + { + "id": 23577, + "owner_id": -60114472, + "from_id": -60114472, + "date": 1438743721, + "post_type": "post", + "text": "René Magritte", + "attachments": [ + { + "type": "photo", + "photo": { + "id": 375542583, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a54/j29vXksmjtw.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a55/_inafzIXl6o.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a56/JQ58ZpF7T98.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a57/cEhY5JqPABw.jpg", + "width": 640, + "height": 532, + "text": "", + "date": 1438743720, + "access_key": "3d8a69e9341e4e44ec" + } + }, + { + "type": "photo", + "photo": { + "id": 375542584, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a5c/LRUr-ydV7ls.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a5d/ciOtHI88vP0.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a5e/rftPC6GvRyQ.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a5f/zCtqiD0EF04.jpg", + "width": 640, + "height": 799, + "text": "", + "date": 1438743720, + "access_key": "e48368517e6a8e40b4" + } + }, + { + "type": "photo", + "photo": { + "id": 375542585, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a64/_bJgQpcgrCs.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a65/3ebcbffCBFs.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a66/9pmrLtry6aE.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a67/-xMdKLMKxM8.jpg", + "width": 500, + "height": 700, + "text": "", + "date": 1438743720, + "access_key": "dfb59f861e40c302a0" + } + }, + { + "type": "photo", + "photo": { + "id": 375542586, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a6c/Eb1Pw97d8eA.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a6d/RIqRAdkMqaQ.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a6e/BsfgVP9YbBg.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a6f/n3jpPk3QG-4.jpg", + "width": 640, + "height": 351, + "text": "", + "date": 1438743720, + "access_key": "9b2e6deb9886ce6b61" + } + }, + { + "type": "photo", + "photo": { + "id": 375542587, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a74/b_ivrxTPuCk.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a75/2mC0wLr14rY.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a76/IqiEm_LOvEA.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a77/kP1O2I4kRi0.jpg", + "width": 640, + "height": 480, + "text": "", + "date": 1438743720, + "access_key": "cf4c1d0dc3bc4c1e07" + } + }, + { + "type": "photo", + "photo": { + "id": 375542588, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a7c/oR5QFjFZ6AM.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a7d/1clxLbH68LM.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a7e/UVzIS9L9No8.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a7f/lnDK5g2U8Ww.jpg", + "photo_1280": "https://pp.vk.me/c543101/v543101677/26a80/nf1UMlRiCy0.jpg", + "width": 640, + "height": 843, + "text": "", + "date": 1438743720, + "access_key": "22cace3b223e511a59" + } + }, + { + "type": "photo", + "photo": { + "id": 375542589, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a85/ImP5oYSw_rg.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a86/I3D8WGB6qzI.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a87/PylA1209YpE.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a88/_JW0W06DwjU.jpg", + "photo_1280": "https://pp.vk.me/c543101/v543101677/26a89/0h_oeDL1mQo.jpg", + "width": 640, + "height": 869, + "text": "", + "date": 1438743720, + "access_key": "a1161d3406f887a021" + } + }, + { + "type": "photo", + "photo": { + "id": 375542590, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a8e/reBCRflPqUc.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a8f/pPfh5BxfoQU.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a90/3MBQfGrEhwY.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a91/zdpgvjpLA7U.jpg", + "width": 640, + "height": 526, + "text": "", + "date": 1438743720, + "access_key": "81e00501271e98c8af" + } + }, + { + "type": "photo", + "photo": { + "id": 375542591, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a96/qhlqwJRED20.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a97/c5TlU2G4cws.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26a98/cvIkwyIEBME.jpg", + "photo_807": "https://pp.vk.me/c543101/v543101677/26a99/XyNPm9aljK0.jpg", + "width": 640, + "height": 798, + "text": "", + "date": 1438743720, + "access_key": "f5b0c2cdec3c770910" + } + }, + { + "type": "photo", + "photo": { + "id": 375542592, + "album_id": -7, + "owner_id": -60114472, + "user_id": 100, + "photo_75": "https://pp.vk.me/c543101/v543101677/26a9e/5Y8x_UVykgA.jpg", + "photo_130": "https://pp.vk.me/c543101/v543101677/26a9f/piwJlIg7jMY.jpg", + "photo_604": "https://pp.vk.me/c543101/v543101677/26aa0/Bbmw97OK6ag.jpg", + "width": 398, + "height": 600, + "text": "", + "date": 1438743720, + "access_key": "fe711c8eb518cc4499" + } + } + ], + "post_source": { + "type": "api" + } + } + ], + "can_edit": 1, + "can_delete": 1, + "can_pin": 1, + "post_source": { + "type": "vk" + }, + "comments": { + "count": 0, + "can_post": 1 + }, + "likes": { + "count": 0, + "user_likes": 0, + "can_like": 1, + "can_publish": 0 + }, + "reposts": { + "count": 0, + "user_reposted": 0 + } + }, + "copy_owner": { + "id": 60114472, + "name": "Albertina", + "screen_name": "al_bertina", + "is_closed": 0, + "type": "page", + "is_admin": 0, + "is_member": 1, + "photo_50": "https://pp.vk.me/c312927/v312927711/4e8d/Gd1mm_PHYaI.jpg", + "photo_100": "https://pp.vk.me/c312927/v312927711/4e8c/mEkXL9VFsEA.jpg", + "photo_200": "https://pp.vk.me/c312927/v312927711/4e8b/8zPo3HESmow.jpg" + } + } +} \ No newline at end of file From 138511428651a0abcd8d870b98d7fd435ee88f70 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Fri, 7 Aug 2015 13:12:11 +0300 Subject: [PATCH 10/18] instagram field in VKontakteProfile --- .../springframework/social/vkontakte/api/VKontakteProfile.java | 1 + .../social/vkontakte/api/impl/json/VKontakteProfileMixin.java | 1 + 2 files changed, 2 insertions(+) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java index bab98c4..3717616 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java @@ -61,6 +61,7 @@ public VKontakteProfile() { private String facebook; private String facebookName; private String twitter; + private String instagram; private String site; private String status; private int commonCount; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java index e76aa4a..803c701 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java @@ -97,6 +97,7 @@ class VKontakteProfileMixin { private String facebookName; @JsonProperty("twitter") private String twitter; + private String instagram; @JsonProperty("site") private String site; @JsonProperty("status") From e8866029cf8fffb1f4c897fe56eb536dc76fa405 Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Mon, 10 Aug 2015 11:52:41 +0300 Subject: [PATCH 11/18] getter and setter for instagram --- .../social/vkontakte/api/VKontakteProfile.java | 8 ++++++++ .../vkontakte/api/impl/json/VKontakteProfileMixin.java | 1 - .../social/vkontakte/api/impl/UsersTemplateTest.java | 3 +-- .../social/vkontakte/api/impl/UtilsTemplateTest.java | 2 -- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java index 3717616..c61343f 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakteProfile.java @@ -93,6 +93,14 @@ public VKontakteProfile() { private LastSeen lastSeen; private Counters counters; + public String getInstagram() { + return instagram; + } + + public void setInstagram(String instagram) { + this.instagram = instagram; + } + public Counters getCounters() { return counters; } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java index 803c701..5fd497c 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteProfileMixin.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.springframework.social.vkontakte.api.*; diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index 1b5be1e..a1553e6 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -20,12 +20,10 @@ import org.springframework.social.vkontakte.api.VKontakteErrorException; import org.springframework.social.vkontakte.api.VKontakteProfile; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; -import static org.springframework.http.HttpMethod.GET; import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; @@ -51,6 +49,7 @@ public void getUser_currentUser() { assertEquals("Дуров", profile.getLastName()); assertEquals(705, profile.getCounters().getFriends()); assertEquals(12, profile.getCounters().getUserPhotos()); + assertEquals("durov", profile.getInstagram()); } @Test diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java index f44f1ad..7acbbb2 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UtilsTemplateTest.java @@ -15,8 +15,6 @@ */ package org.springframework.social.vkontakte.api.impl; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; import org.junit.Test; import org.springframework.social.vkontakte.api.VKGenericResponse; import org.springframework.social.vkontakte.api.VKObject; From 92e0ed8a84fe35de09eabbf1b984c1856d25d87d Mon Sep 17 00:00:00 2001 From: dIsoVi Date: Mon, 10 Aug 2015 12:32:46 +0300 Subject: [PATCH 12/18] fix for NameCase and Order usage --- .../social/vkontakte/api/impl/FriendsTemplate.java | 9 ++++++--- .../social/vkontakte/api/impl/UsersTemplate.java | 3 +-- .../social/vkontakte/api/impl/UsersTemplateTest.java | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java index fdd92a2..8ecf0c2 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/FriendsTemplate.java @@ -17,7 +17,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.social.vkontakte.api.*; +import org.springframework.social.vkontakte.api.ApiVersion; +import org.springframework.social.vkontakte.api.IFriendsOperations; +import org.springframework.social.vkontakte.api.VKGenericResponse; +import org.springframework.social.vkontakte.api.VKontakteProfile; import org.springframework.social.vkontakte.api.impl.json.VKArray; import org.springframework.social.vkontakte.api.vkenums.FriendsOrder; import org.springframework.social.vkontakte.api.vkenums.NameCase; @@ -79,10 +82,10 @@ public VKArray get(Long userId, String fields, FriendsOrder or props.put("fields", fields); } if (order != FriendsOrder.NONE) { - props.put("order", order); + props.put("order", order.toString()); } if (nameCase != NameCase.nom) { - props.put("name_case", nameCase); + props.put("name_case", nameCase.toString()); } URI uri = makeOperationURL("friends.get", props, ApiVersion.VERSION_5_27); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java index a3cb1da..acdb7e3 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/UsersTemplate.java @@ -27,7 +27,6 @@ import java.net.URI; import java.util.List; -import java.util.Properties; /** * User operations. @@ -63,7 +62,7 @@ public List getUsers(List userIds, String fields, Name data.set("user_ids", sb.toString()); } if (nameCase != NameCase.nom) { - data.set("name_case", nameCase); + data.set("name_case", nameCase.toString()); } data.set("fields", fields != null? fields: IUsersOperations.DEFAULT_FIELDS); diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java index a1553e6..9805c46 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/UsersTemplateTest.java @@ -19,6 +19,7 @@ import org.springframework.social.MissingAuthorizationException; import org.springframework.social.vkontakte.api.VKontakteErrorException; import org.springframework.social.vkontakte.api.VKontakteProfile; +import org.springframework.social.vkontakte.api.vkenums.NameCase; import java.util.Arrays; import java.util.List; @@ -58,7 +59,7 @@ public void getUsers_currentUser() { .expect(requestTo("https://api.vk.com/method/users.get")) .andExpect(method(POST)).andRespond(withSuccess(jsonResource("list-of-profiles-5_27"), APPLICATION_JSON)); String[] userIds = {"durov", "2183", "77478"}; - List profiles = vkontakte.usersOperations().getUsers(Arrays.asList(userIds)); + List profiles = vkontakte.usersOperations().getUsers(Arrays.asList(userIds), null, NameCase.abl); assertProfiles(profiles); } From 04a0da6c604030eef13073ca5c53c69304ba90e0 Mon Sep 17 00:00:00 2001 From: Kviz Date: Wed, 18 Nov 2015 16:15:53 +0300 Subject: [PATCH 13/18] Implemented https://api.vk.com/method/wall.getComments --- .../social/vkontakte/api/ApiVersion.java | 3 +- .../social/vkontakte/api/Comment.java | 67 ++++++++ .../vkontakte/api/CommentsResponse.java | 40 +++++ .../social/vkontakte/api/IWallOperations.java | 10 ++ .../vkontakte/api/impl/CommentsRequest.java | 32 ++++ .../vkontakte/api/impl/WallTemplate.java | 53 ++++++ .../vkontakte/api/impl/json/CommentMixin.java | 29 ++++ .../api/impl/json/VKontakteModule.java | 1 + .../vkontakte/api/vkenums/SortOrder.java | 11 ++ .../vkontakte/api/impl/WallTemplateTest.java | 55 ++++++- .../impl/wall-getComments-response-5_33.json | 153 ++++++++++++++++++ 11 files changed, 451 insertions(+), 3 deletions(-) create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java create mode 100644 spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/wall-getComments-response-5_33.json diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/ApiVersion.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/ApiVersion.java index 9723152..f5e37f7 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/ApiVersion.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/ApiVersion.java @@ -10,7 +10,8 @@ public enum ApiVersion { VERSION_5_7("5.7"), VERSION_5_8("5.8"), VERSION_5_21("5.21"), - VERSION_5_27("5.27"); + VERSION_5_27("5.27"), + VERSION_5_33("5.33"); private String version; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java new file mode 100644 index 0000000..6aa4658 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java @@ -0,0 +1,67 @@ +package org.springframework.social.vkontakte.api; + +import org.springframework.social.vkontakte.api.attachment.Attachment; +import org.springframework.util.StringUtils; + +import java.util.Date; +import java.util.List; + +/** + * Model class representing a comment on a post on a user wall or community wall. + * + * @author wiikviz + * @see Comment object | Developers | VK + */ +public class Comment { + private long id; + private long fromId; + private Date date; + private String text; + private long replyToUser; + private long replyToComment; + private Post.Likes likes; + private List attachments; + + public long getFromId() { + return fromId; + } + + public Date getDate() { + return date; + } + + public String getText() { + return text; + } + + public long getId() { + return id; + } + + public long getReplyToUser() { + return replyToUser; + } + + public long getReplyToComment() { + return replyToComment; + } + + public Post.Likes getLikes() { + return likes; + } + + public List getAttachments() { + return attachments; + } + + @Override + public String toString() { + return "Comment{" + + "id='" + id + '\'' + + ", date=" + date + + ", text='" + text + '\'' + + ", likes=" + likes + + ", attachments=" + (attachments == null ? null : StringUtils.collectionToDelimitedString(attachments, ",\n")) + + '}'; + } +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java new file mode 100644 index 0000000..4660d72 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java @@ -0,0 +1,40 @@ +package org.springframework.social.vkontakte.api; + +import java.util.List; + +/** + * https://vk.com/dev/wall.getComments response + * + * @author wiikviz + */ +public class CommentsResponse { + private long count; + private List comments; + private List profiles; + private List groups; + private Long realOffset; + + public CommentsResponse(List comments, long count, Long realOffset, List profiles, List groups) { + this.comments = comments; + this.count = count; + this.realOffset = realOffset; + this.groups = groups; + this.profiles = profiles; + } + + public long getCount() { + return count; + } + + public long getRealOffset() { + return realOffset; + } + + public List getComments() { + return comments; + } + + public List getProfiles() { + return profiles; + } +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java index b5a93b5..8980723 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java @@ -15,6 +15,8 @@ */ package org.springframework.social.vkontakte.api; +import org.springframework.social.vkontakte.api.impl.CommentsRequest; + import java.util.List; /** @@ -62,4 +64,12 @@ public interface IWallOperations { PostStatus post(PostData postData); + /** + * Returns a response that contains a list of comments on a post on a user wall or community wall. + * + * @param request {@link CommentsRequest} + * @return a {@link CommentsResponse}, object representing the response on request of comments on a post on a user's or community's wall + * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. + */ + CommentsResponse getComments(CommentsRequest request); } \ No newline at end of file diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java new file mode 100644 index 0000000..7b9c4b9 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java @@ -0,0 +1,32 @@ +package org.springframework.social.vkontakte.api.impl; + +import org.springframework.social.vkontakte.api.vkenums.SortOrder; + +/** + * https://vk.com/dev/wall.getComments request + * + * @author wiikviz + */ +public class CommentsRequest { + public String ownerId; + public Integer postId; + public boolean needLikes = false; + public Integer startCommentId; + public Integer offset; + public Integer count; + public SortOrder sort; + public Integer previewLength; + public boolean extended = false; + + public CommentsRequest(String ownerId, Integer postId, boolean needLikes, Integer startCommentId, Integer offset, Integer count, SortOrder sort, Integer previewLength, boolean extended) { + this.ownerId = ownerId; + this.postId = postId; + this.needLikes = needLikes; + this.startCommentId = startCommentId; + this.offset = offset; + this.count = count; + this.sort = sort; + this.previewLength = previewLength; + this.extended = extended; + } +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java index 6880d04..e8b232b 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java @@ -16,8 +16,11 @@ package org.springframework.social.vkontakte.api.impl; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import org.springframework.social.UncategorizedApiException; import org.springframework.social.vkontakte.api.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; @@ -90,4 +93,54 @@ public PostStatus post(PostData postData) { return response.getStatus(); } + + @Override + public CommentsResponse getComments(CommentsRequest request) { + MultiValueMap data = new LinkedMultiValueMap(); + + data.set("owner_id", request.ownerId); + data.set("post_id", request.postId.toString()); + if (request.needLikes) { + data.set("need_likes", "1"); + } + if (request.startCommentId != null && request.startCommentId > 0) { + data.set("start_comment_id", request.startCommentId.toString()); + } + if (request.offset != null && request.offset > 0) { + data.set("offset", request.offset.toString()); + } + if (request.count != null && request.count > 0) { + data.set("count", request.count.toString()); + } + if (request.sort != null) { + data.set("sort", request.sort.toString()); + } + if (request.previewLength != null && request.previewLength > 0) { + data.set("preview_length", request.previewLength.toString()); + } else { + //Specify 0 as it does not want to truncate comments. + data.set("preview_length", "0"); + } + if (request.extended) { + data.set("extended", "1"); + } + + URI uri = makeOperationPOST("wall.getComments", data, ApiVersion.VERSION_5_33); + VKGenericResponse response = restTemplate.postForObject(uri, data, VKGenericResponse.class); + checkForError(response); + + List comments = deserializeVK50ItemsResponse(response, Comment.class).getItems(); + List profiles = null; + List groups = null; + if (request.extended) { + profiles = deserializeItems((ArrayNode) response.getResponse().get("profiles"), VKontakteProfile.class); + groups = deserializeItems((ArrayNode) response.getResponse().get("groups"), Group.class); + } + long count = response.getResponse().get("count").asLong(); + Long realOffset = null; + if (request.startCommentId != null) { + realOffset = response.getResponse().get("real_offset").asLong(); + } + return new CommentsResponse(comments, count, realOffset, profiles, groups); + } } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java new file mode 100644 index 0000000..01b084b --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java @@ -0,0 +1,29 @@ +package org.springframework.social.vkontakte.api.impl.json; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.springframework.social.vkontakte.api.impl.json.deserializers.UnixTimeDeserializer; + +import java.util.Date; + +/** + * Mixin for {@link org.springframework.social.vkontakte.api.Comment} + * + * @author wiikviz + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class CommentMixin { + @JsonProperty("from_id") + long fromId; + + @JsonProperty("date") + @JsonDeserialize(using = UnixTimeDeserializer.class) + Date date; + + @JsonProperty("reply_to_user") + long replyToUser; + + @JsonProperty("reply_to_comment") + long replyToComment; +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java index 241ce39..319997f 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/VKontakteModule.java @@ -50,6 +50,7 @@ public void setupModule(SetupContext context) { context.setMixInAnnotations(Post.Comments.class, PostCommentsMixin.class); context.setMixInAnnotations(Post.Geo.class, PostGeoMixin.class); context.setMixInAnnotations(Place.class, PostGeoPlaceMixin.class); + context.setMixInAnnotations(Comment.class, CommentMixin.class); context.setMixInAnnotations(Group.class, GroupMixin.class); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java new file mode 100644 index 0000000..4a031d1 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java @@ -0,0 +1,11 @@ +package org.springframework.social.vkontakte.api.vkenums; + +/** + * https://vk.com/dev/wall.getComments sort + * + * @author wiikviz + */ +public enum SortOrder { + asc, + desc +} diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java index 1892a50..8d95719 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java @@ -16,15 +16,23 @@ package org.springframework.social.vkontakte.api.impl; import org.junit.Test; +import org.springframework.core.env.SystemEnvironmentPropertySource; +import org.springframework.social.InternalServerErrorException; +import org.springframework.social.vkontakte.api.Comment; +import org.springframework.social.vkontakte.api.CommentsResponse; import org.springframework.social.vkontakte.api.Post; +import org.springframework.social.vkontakte.api.VKontakteProfile; import org.springframework.social.vkontakte.api.attachment.*; +import org.springframework.social.vkontakte.api.vkenums.SortOrder; import java.util.List; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.MediaType.APPLICATION_JSON; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; /** @@ -32,6 +40,7 @@ * @author vkolodrevskiy */ public class WallTemplateTest extends AbstractVKontakteApiTest { + @Test public void getPosts() { mockServer.expect(requestTo("https://api.vk.com/method/wall.get?access_token=ACCESS_TOKEN&v=5.27")) @@ -43,7 +52,49 @@ public void getPosts() { assertEquals(AttachmentType.PHOTOS_LIST, photosListAttachment.getType()); assertEquals(306810815, ((PhotosListAttachment)photosListAttachment).getPhotosList().get(0).getPhotoId()); assertEquals(45555, posts.get(1).getId()); + assertEquals(22694, posts.get(1).getLikes().getCount()); + assertEquals(false, posts.get(1).getLikes().isUserLikes()); assertEquals(2, posts.get(1).getAttachments().size()); assertEquals(3, ((StickerAttachment)posts.get(22).getCopyHistory().get(0).getAttachments().get(0)).getSticker().getProductId()); } + + @Test + public void getComments() { + mockServer + .expect(requestTo("https://api.vk.com/method/wall.getComments")) + .andExpect(method(POST)) + .andExpect(content().string("owner_id=85635407&post_id=3199&need_likes=1&start_comment_id=3204&offset=2&count=3&sort=desc&preview_length=9999&extended=1&access_token=ACCESS_TOKEN&v=5.33")) + .andRespond(withSuccess(jsonResource("wall-getComments-response-5_33"), APPLICATION_JSON)); + CommentsRequest request = new CommentsRequest("85635407", 3199, true, 3204, 2, 3, SortOrder.desc, 9999, true); + + CommentsResponse response = vkontakte.wallOperations().getComments(request); + + assertEquals(16, response.getCount()); + assertEquals(10, response.getRealOffset()); + + assertEquals(6, response.getComments().size()); + assertEquals(4, response.getProfiles().size()); + + assertComment(response.getComments().get(0)); + assertProfile(response.getProfiles().get(0)); + } + + private void assertComment(Comment comment) { + assertEquals(3205, comment.getId()); + assertEquals(1375980597000L, comment.getDate().getTime()); + assertEquals(85635407, comment.getFromId()); + assertEquals("[id3197366|Андрей], поправил", comment.getText()); + assertEquals(3197366, comment.getReplyToUser()); + assertEquals(3200, comment.getReplyToComment()); + assertEquals(666, comment.getLikes().getCount()); + assertEquals(true, comment.getLikes().isUserLikes()); + assertEquals(2, comment.getAttachments().size()); + } + + private void assertProfile(VKontakteProfile profile) { + assertEquals(3197366, profile.getId()); + assertEquals("suppo", profile.getScreenName()); + assertEquals("M", profile.getGender()); + assertEquals(true, profile.isOnline()); + } } diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/wall-getComments-response-5_33.json b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/wall-getComments-response-5_33.json new file mode 100644 index 0000000..ddf6bcc --- /dev/null +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/wall-getComments-response-5_33.json @@ -0,0 +1,153 @@ +{ + "response": { + "count": 16, + "real_offset": 10, + "items": [ + { + "id": 3205, + "from_id": 85635407, + "date": 1375980597, + "text": "[id3197366|Андрей], поправил", + "likes": { + "count": 666, + "user_likes": 1, + "can_like": 1 + }, + "reply_to_user": 3197366, + "reply_to_comment": 3200, + "attachments": [ + { + "type": "photo", + "photo": { + "id": 308701914, + "album_id": -5, + "owner_id": 85635407, + "photo_75": "https:\/\/pp.vk.me\/c6035\/v6035288\/6ef0\/q4rguINFKc0.jpg", + "photo_130": "https:\/\/pp.vk.me\/c6035\/v6035288\/6ef1\/sjEQyroiYac.jpg", + "photo_604": "https:\/\/pp.vk.me\/c6035\/v6035288\/6ef2\/24e6zf6JT8E.jpg", + "width": 591, + "height": 118, + "text": "Original: http:\/\/s2.1pic.org\/files\/2013\/08\/08\/e89e7b5e6b7cfe6d8aa5.jpg", + "date": 1375979968, + "access_key": "f5083a22fe3d0b6f2f" + } + }, + { + "type": "audio", + "audio": { + "id": 283017386, + "owner_id": 85635407, + "artist": "San Cisco", + "title": "Beach", + "duration": 227, + "url": "http://cs6191.vk.me/u156280183/audios/7453f3072442.mp3?extra=DtlNCRK0Wf-9AiLZiBKfB7rTCZjeeF2C7ri88acWH0rk-meDbDZMbGmTBaygzzeklPz7qxOlpASUpLjeJmNJCi0aVxUkz9w", + "lyrics_id": 125602217, + "album_id": 2, + "genre_id": 9 + } + } + ] + }, + { + "id": 3204, + "from_id": 85635407, + "date": 1375980529, + "text": "[id19498153|Макс], не могу =(", + "likes": { + "count": 0, + "user_likes": 0, + "can_like": 1 + }, + "reply_to_user": 19498153, + "reply_to_comment": 3203 + }, + { + "id": 3203, + "from_id": 19498153, + "date": 1375980513, + "text": "Лимит увеличь, молю!", + "likes": { + "count": 2, + "user_likes": 0, + "can_like": 1 + } + }, + { + "id": 3202, + "from_id": 40001922, + "date": 1375980076, + "text": "Наконец-то! Спасибо.", + "likes": { + "count": 2, + "user_likes": 0, + "can_like": 1 + } + }, + { + "id": 3201, + "from_id": 3197366, + "date": 1375979984, + "text": "И, я думаю, если я не админ, то мне не нужны фотографии сообщества, не?", + "likes": { + "count": 0, + "user_likes": 0, + "can_like": 1 + } + }, + { + "id": 3200, + "from_id": 3197366, + "date": 1375979966, + "text": "Однако баг:", + "likes": { + "count": 1, + "user_likes": 0, + "can_like": 1 + } + } + ], + "profiles": [ + { + "id": 3197366, + "first_name": "Андрей", + "last_name": "Андреев", + "sex": 2, + "screen_name": "suppo", + "photo_50": "https:\/\/pp.vk.me\/c629516\/v629516366\/2509e\/j1RWzBSsx34.jpg", + "photo_100": "https:\/\/pp.vk.me\/c629516\/v629516366\/2509d\/Y_WW-9c59KA.jpg", + "online": 1 + }, + { + "id": 19498153, + "first_name": "Максим", + "last_name": "Долженко", + "sex": 2, + "screen_name": "md", + "photo_50": "https:\/\/pp.vk.me\/c624816\/v624816153\/3866c\/bkxkxJ0xn5I.jpg", + "photo_100": "https:\/\/pp.vk.me\/c624816\/v624816153\/3866b\/fyT0u8Fr0Jo.jpg", + "online": 1 + }, + { + "id": 40001922, + "first_name": "Sergey", + "last_name": "Golitsyn", + "sex": 2, + "screen_name": "golitsyn", + "photo_50": "https:\/\/pp.vk.me\/c311621\/v311621922\/9ac0\/qtqzaeBwJkA.jpg", + "photo_100": "https:\/\/pp.vk.me\/c311621\/v311621922\/9abf\/0oziI23A7gI.jpg", + "online": 0 + }, + { + "id": 85635407, + "first_name": "Олег", + "last_name": "Илларионов", + "sex": 2, + "screen_name": "derp", + "photo_50": "https:\/\/pp.vk.me\/c620831\/v620831407\/1638f\/6qaLGdESeIw.jpg", + "photo_100": "https:\/\/pp.vk.me\/c620831\/v620831407\/1638e\/wKAZXphhssY.jpg", + "online": 0 + } + ], + "groups": [] + } +} \ No newline at end of file From 4512ad0e1af1d26bac1ab725fa37c0fafe7e08e3 Mon Sep 17 00:00:00 2001 From: Kviz Date: Mon, 23 Nov 2015 16:33:11 +0300 Subject: [PATCH 14/18] Implemented CommentsRequest.Builder, the fluent builder for CommentsRequest --- .../vkontakte/api/CommentsResponse.java | 15 ++- .../social/vkontakte/api/IWallOperations.java | 8 +- .../vkontakte/api/impl/CommentsRequest.java | 32 ------ .../vkontakte/api/impl/WallTemplate.java | 49 +++++--- .../api/impl/wall/CommentsQuery.java | 108 ++++++++++++++++++ .../api/impl/wall/CommunityWall.java | 22 ++++ .../vkontakte/api/impl/wall/UserWall.java | 22 ++++ .../vkontakte/api/impl/wall/WallOwner.java | 21 ++++ .../vkontakte/api/impl/WallTemplateTest.java | 30 +++-- 9 files changed, 241 insertions(+), 66 deletions(-) delete mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java create mode 100644 spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java index 4660d72..36b3484 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java @@ -1,18 +1,21 @@ package org.springframework.social.vkontakte.api; +import org.springframework.social.vkontakte.api.impl.wall.CommentsQuery; + import java.util.List; /** - * https://vk.com/dev/wall.getComments response + * Model class representing a response that contains a list of comments on a post on a user wall or community wall. * * @author wiikviz + * @see IWallOperations#getComments(CommentsQuery) */ public class CommentsResponse { - private long count; - private List comments; - private List profiles; - private List groups; - private Long realOffset; + private final long count; + private final List comments; + private final List profiles; + private final List groups; + private final Long realOffset; public CommentsResponse(List comments, long count, Long realOffset, List profiles, List groups) { this.comments = comments; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java index 8980723..d7e9589 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IWallOperations.java @@ -15,7 +15,7 @@ */ package org.springframework.social.vkontakte.api; -import org.springframework.social.vkontakte.api.impl.CommentsRequest; +import org.springframework.social.vkontakte.api.impl.wall.CommentsQuery; import java.util.List; @@ -67,9 +67,9 @@ public interface IWallOperations { /** * Returns a response that contains a list of comments on a post on a user wall or community wall. * - * @param request {@link CommentsRequest} - * @return a {@link CommentsResponse}, object representing the response on request of comments on a post on a user's or community's wall + * @param query {@link CommentsQuery} + * @return a {@link CommentsResponse}, object representing the response on query of comments on a post on a user's or community's wall * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ - CommentsResponse getComments(CommentsRequest request); + CommentsResponse getComments(CommentsQuery query); } \ No newline at end of file diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java deleted file mode 100644 index 7b9c4b9..0000000 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/CommentsRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.springframework.social.vkontakte.api.impl; - -import org.springframework.social.vkontakte.api.vkenums.SortOrder; - -/** - * https://vk.com/dev/wall.getComments request - * - * @author wiikviz - */ -public class CommentsRequest { - public String ownerId; - public Integer postId; - public boolean needLikes = false; - public Integer startCommentId; - public Integer offset; - public Integer count; - public SortOrder sort; - public Integer previewLength; - public boolean extended = false; - - public CommentsRequest(String ownerId, Integer postId, boolean needLikes, Integer startCommentId, Integer offset, Integer count, SortOrder sort, Integer previewLength, boolean extended) { - this.ownerId = ownerId; - this.postId = postId; - this.needLikes = needLikes; - this.startCommentId = startCommentId; - this.offset = offset; - this.count = count; - this.sort = sort; - this.previewLength = previewLength; - this.extended = extended; - } -} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java index e8b232b..e3e5dd6 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import org.springframework.social.UncategorizedApiException; import org.springframework.social.vkontakte.api.*; +import org.springframework.social.vkontakte.api.impl.wall.CommentsQuery; +import org.springframework.social.vkontakte.api.impl.wall.CommunityWall; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; @@ -30,6 +32,7 @@ /** * {@link org.springframework.social.vkontakte.api.IWallOperations} implementation. + * * @author vkolodrevskiy */ public class WallTemplate extends AbstractVKontakteOperations implements IWallOperations { @@ -95,33 +98,45 @@ public PostStatus post(PostData postData) { } @Override - public CommentsResponse getComments(CommentsRequest request) { + public CommentsResponse getComments(CommentsQuery query) { MultiValueMap data = new LinkedMultiValueMap(); - data.set("owner_id", request.ownerId); - data.set("post_id", request.postId.toString()); - if (request.needLikes) { + if (query.owner instanceof CommunityWall) { + data.set("owner_id", "-" + String.valueOf(query.owner.getId())); + } else { + data.set("owner_id", String.valueOf(query.owner.getId())); + } + + data.set("post_id", String.valueOf(query.postId)); + + if (query.needLikes) { data.set("need_likes", "1"); } - if (request.startCommentId != null && request.startCommentId > 0) { - data.set("start_comment_id", request.startCommentId.toString()); + + if (query.startCommentId != null && query.startCommentId > 0) { + data.set("start_comment_id", query.startCommentId.toString()); } - if (request.offset != null && request.offset > 0) { - data.set("offset", request.offset.toString()); + + if (query.offset != null && query.offset > 0) { + data.set("offset", query.offset.toString()); } - if (request.count != null && request.count > 0) { - data.set("count", request.count.toString()); + + if (query.count != null && query.count > 0) { + data.set("count", query.count.toString()); } - if (request.sort != null) { - data.set("sort", request.sort.toString()); + + if (query.sort != null) { + data.set("sort", query.sort.toString()); } - if (request.previewLength != null && request.previewLength > 0) { - data.set("preview_length", request.previewLength.toString()); + + if (query.previewLength != null && query.previewLength > 0) { + data.set("preview_length", query.previewLength.toString()); } else { //Specify 0 as it does not want to truncate comments. data.set("preview_length", "0"); } - if (request.extended) { + + if (query.extended) { data.set("extended", "1"); } @@ -132,13 +147,13 @@ public CommentsResponse getComments(CommentsRequest request) { List comments = deserializeVK50ItemsResponse(response, Comment.class).getItems(); List profiles = null; List groups = null; - if (request.extended) { + if (query.extended) { profiles = deserializeItems((ArrayNode) response.getResponse().get("profiles"), VKontakteProfile.class); groups = deserializeItems((ArrayNode) response.getResponse().get("groups"), Group.class); } long count = response.getResponse().get("count").asLong(); Long realOffset = null; - if (request.startCommentId != null) { + if (query.startCommentId != null) { realOffset = response.getResponse().get("real_offset").asLong(); } return new CommentsResponse(comments, count, realOffset, profiles, groups); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java new file mode 100644 index 0000000..f384ea2 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java @@ -0,0 +1,108 @@ +package org.springframework.social.vkontakte.api.impl.wall; + +import org.springframework.social.vkontakte.api.IWallOperations; +import org.springframework.social.vkontakte.api.vkenums.SortOrder; + +/** + * Model class representing query for the list of comments on a post on a user wall or community wall. + * + * @author wiikviz + * @see IWallOperations#getComments(CommentsQuery) + * @see wall.getComments | Developers | VK + */ +public final class CommentsQuery { + public final WallOwner owner; + public final int postId; + public final boolean needLikes; + public final Integer startCommentId; + public final Integer offset; + public final Integer count; + public final SortOrder sort; + public final Integer previewLength; + public final boolean extended; + + public CommentsQuery(WallOwner owner, int postId, boolean needLikes, Integer startCommentId, Integer offset, Integer count, SortOrder sort, Integer previewLength, boolean extended) { + this.owner = owner; + this.postId = postId; + this.needLikes = needLikes; + this.startCommentId = startCommentId; + this.offset = offset; + this.count = count; + this.sort = sort; + this.previewLength = previewLength; + this.extended = extended; + } + + @Override + public String toString() { + return "CommentsQuery{" + + "owner='" + owner + '\'' + + ", postId=" + postId + + '}'; + } + + public static class Builder { + private WallOwner owner; + private Integer postId; + private boolean needLikes; + private Integer startCommentId; + private Integer offset; + private Integer count; + private SortOrder sort; + private Integer previewLength; + private boolean extended; + + /** + * @param owner {@link UserWall} or {@link UserWall} + * @param postId post ID. + */ + public Builder(WallOwner owner, int postId) { + this.owner = owner; + this.postId = postId; + } + + public Builder needLikes(boolean needLikes) { + this.needLikes = needLikes; + return this; + } + + public Builder startCommentId(int startCommentId) { + this.startCommentId = startCommentId; + return this; + } + + public Builder offset(int offset) { + this.offset = offset; + return this; + } + + public Builder count(int count) { + this.count = count; + return this; + } + + public Builder sort(SortOrder sort) { + this.sort = sort; + return this; + } + + /** + * @param previewLength number of characters at which to truncate comments when previewed. + * If {@code null} or {@code 0} comments are not truncated. + * @return {@link org.springframework.social.vkontakte.api.impl.wall.CommentsQuery.Builder} + */ + public Builder previewLength(int previewLength) { + this.previewLength = previewLength; + return this; + } + + public Builder extended(boolean extended) { + this.extended = extended; + return this; + } + + public CommentsQuery build() { + return new CommentsQuery(owner, postId, needLikes, startCommentId, offset, count, sort, previewLength, extended); + } + } +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java new file mode 100644 index 0000000..69a43d6 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java @@ -0,0 +1,22 @@ +package org.springframework.social.vkontakte.api.impl.wall; + +/** + * Model class representing community wall owner + * + * @author wiikviz + * @see WallOwner + * @see CommentsQuery#owner + */ +public final class CommunityWall extends WallOwner { + public CommunityWall(final long communityId) { + super(communityId); + } + + @Override + public String toString() { + return "CommunityWall{" + + "id='" + getId() + '\'' + + '}'; + } + +} diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java new file mode 100644 index 0000000..fd4dbed --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java @@ -0,0 +1,22 @@ +package org.springframework.social.vkontakte.api.impl.wall; + +/** + * Model class representing user wall owner + * + * @author wiikviz + * @see WallOwner + * @see CommentsQuery#owner + */ +public final class UserWall extends WallOwner { + public UserWall(final long userId) { + super(userId); + } + + @Override + public String toString() { + return "UserWall{" + + "id='" + getId() + '\'' + + '}'; + } +} + diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java new file mode 100644 index 0000000..c95a176 --- /dev/null +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java @@ -0,0 +1,21 @@ +package org.springframework.social.vkontakte.api.impl.wall; + +/** + * Model class representing an abstract wall's owner + * + * @author wiikviz + * @see UserWall + * @see CommunityWall + * @see CommentsQuery#owner + */ +public abstract class WallOwner { + private final long id; + + protected WallOwner(final long ownerId) { + this.id = ownerId; + } + + public long getId() { + return id; + } +} diff --git a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java index 8d95719..becde61 100644 --- a/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java +++ b/spring-social-vkontakte/src/test/java/org/springframework/social/vkontakte/api/impl/WallTemplateTest.java @@ -16,19 +16,22 @@ package org.springframework.social.vkontakte.api.impl; import org.junit.Test; -import org.springframework.core.env.SystemEnvironmentPropertySource; -import org.springframework.social.InternalServerErrorException; import org.springframework.social.vkontakte.api.Comment; import org.springframework.social.vkontakte.api.CommentsResponse; import org.springframework.social.vkontakte.api.Post; import org.springframework.social.vkontakte.api.VKontakteProfile; -import org.springframework.social.vkontakte.api.attachment.*; +import org.springframework.social.vkontakte.api.attachment.Attachment; +import org.springframework.social.vkontakte.api.attachment.AttachmentType; +import org.springframework.social.vkontakte.api.attachment.PhotosListAttachment; +import org.springframework.social.vkontakte.api.attachment.StickerAttachment; +import org.springframework.social.vkontakte.api.impl.wall.CommentsQuery; +import org.springframework.social.vkontakte.api.impl.wall.CommunityWall; +import org.springframework.social.vkontakte.api.impl.wall.UserWall; import org.springframework.social.vkontakte.api.vkenums.SortOrder; import java.util.List; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; import static org.springframework.http.HttpMethod.GET; import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -40,7 +43,6 @@ * @author vkolodrevskiy */ public class WallTemplateTest extends AbstractVKontakteApiTest { - @Test public void getPosts() { mockServer.expect(requestTo("https://api.vk.com/method/wall.get?access_token=ACCESS_TOKEN&v=5.27")) @@ -59,13 +61,27 @@ public void getPosts() { } @Test - public void getComments() { + public void getCommunityWallComments() { + mockServer + .expect(requestTo("https://api.vk.com/method/wall.getComments")) + .andExpect(method(POST)) + .andExpect(content().string("owner_id=-85635407&post_id=3199&preview_length=0&access_token=ACCESS_TOKEN&v=5.33")) + .andRespond(withSuccess(jsonResource("wall-getComments-response-5_33"), APPLICATION_JSON)); + CommentsQuery request = new CommentsQuery.Builder(new CommunityWall(85635407), 3199).build(); + + CommentsResponse response = vkontakte.wallOperations().getComments(request); + + assertEquals(16, response.getCount()); + } + + @Test + public void getUserWallComments() { mockServer .expect(requestTo("https://api.vk.com/method/wall.getComments")) .andExpect(method(POST)) .andExpect(content().string("owner_id=85635407&post_id=3199&need_likes=1&start_comment_id=3204&offset=2&count=3&sort=desc&preview_length=9999&extended=1&access_token=ACCESS_TOKEN&v=5.33")) .andRespond(withSuccess(jsonResource("wall-getComments-response-5_33"), APPLICATION_JSON)); - CommentsRequest request = new CommentsRequest("85635407", 3199, true, 3204, 2, 3, SortOrder.desc, 9999, true); + CommentsQuery request = new CommentsQuery(new UserWall(85635407), 3199, true, 3204, 2, 3, SortOrder.desc, 9999, true); CommentsResponse response = vkontakte.wallOperations().getComments(request); From eaa452a43852bc68e48c839095f429047f56daf3 Mon Sep 17 00:00:00 2001 From: Kviz Date: Tue, 24 Nov 2015 00:04:40 +0300 Subject: [PATCH 15/18] Follow the guidelines, removed my @author tags. --- .../java/org/springframework/social/vkontakte/api/Comment.java | 1 - .../springframework/social/vkontakte/api/CommentsResponse.java | 1 - .../social/vkontakte/api/impl/json/CommentMixin.java | 2 -- .../social/vkontakte/api/impl/wall/CommentsQuery.java | 1 - .../social/vkontakte/api/impl/wall/CommunityWall.java | 1 - .../social/vkontakte/api/impl/wall/UserWall.java | 1 - .../social/vkontakte/api/impl/wall/WallOwner.java | 1 - .../springframework/social/vkontakte/api/vkenums/SortOrder.java | 1 - 8 files changed, 9 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java index 6aa4658..b601782 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Comment.java @@ -9,7 +9,6 @@ /** * Model class representing a comment on a post on a user wall or community wall. * - * @author wiikviz * @see Comment object | Developers | VK */ public class Comment { diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java index 36b3484..34ace75 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/CommentsResponse.java @@ -7,7 +7,6 @@ /** * Model class representing a response that contains a list of comments on a post on a user wall or community wall. * - * @author wiikviz * @see IWallOperations#getComments(CommentsQuery) */ public class CommentsResponse { diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java index 01b084b..1cf58bf 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/json/CommentMixin.java @@ -9,8 +9,6 @@ /** * Mixin for {@link org.springframework.social.vkontakte.api.Comment} - * - * @author wiikviz */ @JsonIgnoreProperties(ignoreUnknown = true) public class CommentMixin { diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java index f384ea2..85d0354 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java @@ -6,7 +6,6 @@ /** * Model class representing query for the list of comments on a post on a user wall or community wall. * - * @author wiikviz * @see IWallOperations#getComments(CommentsQuery) * @see wall.getComments | Developers | VK */ diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java index 69a43d6..ef20c18 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommunityWall.java @@ -3,7 +3,6 @@ /** * Model class representing community wall owner * - * @author wiikviz * @see WallOwner * @see CommentsQuery#owner */ diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java index fd4dbed..7511a71 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/UserWall.java @@ -3,7 +3,6 @@ /** * Model class representing user wall owner * - * @author wiikviz * @see WallOwner * @see CommentsQuery#owner */ diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java index c95a176..1753477 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/WallOwner.java @@ -3,7 +3,6 @@ /** * Model class representing an abstract wall's owner * - * @author wiikviz * @see UserWall * @see CommunityWall * @see CommentsQuery#owner diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java index 4a031d1..ea5040b 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java @@ -3,7 +3,6 @@ /** * https://vk.com/dev/wall.getComments sort * - * @author wiikviz */ public enum SortOrder { asc, From 841b8c359ce545b6ebda7e6d3b493ce653486ab6 Mon Sep 17 00:00:00 2001 From: Kviz Date: Tue, 24 Nov 2015 16:07:17 +0300 Subject: [PATCH 16/18] small fix --- .../social/vkontakte/api/impl/WallTemplate.java | 1 - .../social/vkontakte/api/impl/wall/CommentsQuery.java | 4 ++++ .../social/vkontakte/api/vkenums/SortOrder.java | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java index e3e5dd6..dc84823 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/WallTemplate.java @@ -97,7 +97,6 @@ public PostStatus post(PostData postData) { return response.getStatus(); } - @Override public CommentsResponse getComments(CommentsQuery query) { MultiValueMap data = new LinkedMultiValueMap(); diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java index 85d0354..b30f3ca 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/wall/CommentsQuery.java @@ -75,6 +75,10 @@ public Builder offset(int offset) { return this; } + /** + * @param count number of comments to return (maximum 100) + * @return {@link org.springframework.social.vkontakte.api.impl.wall.CommentsQuery.Builder} + */ public Builder count(int count) { this.count = count; return this; diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java index ea5040b..1c2301a 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/vkenums/SortOrder.java @@ -1,8 +1,7 @@ package org.springframework.social.vkontakte.api.vkenums; /** - * https://vk.com/dev/wall.getComments sort - * + * Defines sort order for wall.getComments operation */ public enum SortOrder { asc, From 74d299aaa70b1b9c240cfe79afd3cc4996f19ba8 Mon Sep 17 00:00:00 2001 From: Kviz Date: Thu, 3 Dec 2015 23:35:50 +0300 Subject: [PATCH 17/18] Fix Javadoc build errors, resolve vkolodrevskiy/spring-social-vkontakte#50 --- .../social/vkontakte/api/Audio.java | 2 +- .../vkontakte/api/IUsersOperations.java | 59 +++++++++++-------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Audio.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Audio.java index 628b7e9..ed3f9c4 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Audio.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/Audio.java @@ -18,7 +18,7 @@ import java.io.Serializable; /** - * Model class representing audio.
+ * Model class representing audio.
* See definition of this object at http://vk.com/dev/audio_object * * @author vkolodrevskiy diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java index b0641f9..9bfc0c4 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/IUsersOperations.java @@ -21,61 +21,68 @@ /** * User operations. + * * @author vkolodrevskiy */ public interface IUsersOperations { String DEFAULT_FIELDS = "first_name,last_name,photo_50,photo_100,photo_200,contacts,bdate,sex,screen_name"; + /** - * Retrieves the profile for the authenticated user. - * @return the user's profile information. - * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. - * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * Retrieves the profile for the authenticated user. + * + * @return the user's profile information. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. - */ - VKontakteProfile getUser(); + */ + VKontakteProfile getUser(); /** * Retrieves the profile for the authenticated user. + * * @param fields VKontakte fields to retrieve, comma-delimited. * @return the user's profile information. - * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. - * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ VKontakteProfile getUser(String fields); - /** - * Retrieves profiles for specified user unique identifiers. - * @param userIds VKontakte user profile unique identifiers, for which to gt data. - * If null is passed user profile or the current user will be returned. - * @return the user's profile information. - * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. - * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + /** + * Retrieves profiles for specified user unique identifiers. + * + * @param userIds VKontakte user profile unique identifiers, for which to gt data. + * If {@code null} is passed user profile or the current user will be returned. + * @return the user's profile information. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. - */ - List getUsers(List userIds); + */ + List getUsers(List userIds); /** * Retrieves profiles for specified user unique identifiers. + * * @param userIds VKontakte user profile unique identifiers, for which to gt data. - * @param fields VKontakte fields to retrieve, comma-delimited. - * If null is passed user profile or the current user will be returned. + * @param fields VKontakte fields to retrieve, comma-delimited. + * If {@code null} is passed user profile or the current user will be returned. * @return the user's profile information. - * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. - * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ List getUsers(List userIds, String fields); /** * Retrieves profiles for specified user unique identifiers. - * @param userIds VKontakte user profile unique identifiers, for which to gt data. - * @param fields VKontakte fields to retrieve, comma-delimited. - * If null is passed user profile or the current user will be returned. + * + * @param userIds VKontakte user profile unique identifiers, for which to gt data. + * @param fields VKontakte fields to retrieve, comma-delimited. + * If {@code null} is passed user profile or the current user will be returned. * @param nameCase case for declension of user name and surname. * @return the user's profile information. - * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. - * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. + * @throws org.springframework.social.ApiException if there is an error while communicating with VKontakte. + * @throws org.springframework.social.MissingAuthorizationException if VKontakteTemplate was not created with an access token. * @throws org.springframework.social.vkontakte.api.VKontakteErrorException if VKontakte returned error. */ List getUsers(List userIds, String fields, NameCase nameCase); From 90496eeb749c6d95c6e9d2b617d3b1b198c74b3b Mon Sep 17 00:00:00 2001 From: Kviz Date: Thu, 3 Dec 2015 23:43:06 +0300 Subject: [PATCH 18/18] Fix Javadoc warnings, close vkolodrevskiy/spring-social-vkontakte#50 --- .../social/vkontakte/api/VKontakte.java | 35 ++++++++++++++----- .../api/impl/AbstractVKontakteOperations.java | 11 +++--- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakte.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakte.java index bd1c262..f14f8bc 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakte.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/VKontakte.java @@ -23,50 +23,67 @@ * @author vkolodrevskiy */ public interface VKontakte extends ApiBinding { - /** - * API for performing operations on VKontakte user profiles. - */ + * API for performing operations on VKontakte user profiles. + * + * @return {@link IUsersOperations} + */ public IUsersOperations usersOperations(); - /** - * API for performing operations on feeds. - */ + /** + * API for performing operations on feeds. + * + * @return {@link IWallOperations} + */ public IWallOperations wallOperations(); - /** - * API for performing operations with a user's set of friends. - */ + /** + * API for performing operations with a user's set of friends. + * + * @return {@link IFriendsOperations} + */ public IFriendsOperations friendsOperations(); /** * API for performing secure operations. + * + * @return {@link ISecureOperations} */ public ISecureOperations secureOperations(); /** * API for performing operations with a location info. + * + * @return {@link ILocationOperations} */ public ILocationOperations locationOperations(); /** * API for performing operations with audio. + * + * @return {@link IAudioOperations} */ public IAudioOperations audioOperations(); /** * API for performing operations with groups. + * + * @return {@link IGroupsOperations} */ public IGroupsOperations groupsOperations(); /** * API for performing operations with newsfeed. + * + * @return {@link INewsFeedOperations} */ public INewsFeedOperations newsFeedOperations(); /** * API for performing operations with utils. + * + * @return {@link IUtilsOperations} */ public IUtilsOperations utilsOperations(); } diff --git a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java index 3c976ae..d4d9fc2 100644 --- a/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java +++ b/spring-social-vkontakte/src/main/java/org/springframework/social/vkontakte/api/impl/AbstractVKontakteOperations.java @@ -108,10 +108,11 @@ protected VKArray deserializeArray(VKGenericResponse response, Class i /** * for responses of VK API 5.0+ - * @param response - * @param itemClass - * @param - * @return + * + * @param response {@link VKGenericResponse response} + * @param itemClass class of the item + * @param item type + * @return array */ protected VKArray deserializeVK50ItemsResponse(VKGenericResponse response, Class itemClass) { checkForError(response); @@ -119,7 +120,7 @@ protected VKArray deserializeVK50ItemsResponse(VKGenericResponse response JsonNode itemsNode = jsonNode.get("items"); Assert.isTrue(itemsNode.isArray()); int count = jsonNode.get("count").asInt(); - return new VKArray(count, deserializeItems((ArrayNode)itemsNode, itemClass)); + return new VKArray(count, deserializeItems((ArrayNode) itemsNode, itemClass)); } protected List deserializeItems(ArrayNode items, Class itemClass) {