package ru.iris.common.source.vk;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import ru.iris.common.source.vk.entities.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Author: akorobitsyn
* Date: 29.07.13
* Time: 19:20
*/
public class VKConnectorImpl implements VKConnector
{
//getting token
//https://oauth.vk.com/authorize?client_id=3858624&scope=groups,wall,photos,friends,status,offline&redirect_uri=http://oauth.vk.com/blank.html&display=page&response_type=token
private final Log log = LogFactory.getLog(VKConnector.class);
private final static String authUrl = "https://oauth.vk.com/token?grant_type=password&client_id=%d&client_secret=%s&username=%s&password=%s&v=5.25";
private final static String groupsSearchUrl = "https://api.vk.com/method/groups.search?q=%s&offset=%d&count=%d&access_token=%s";
private final static String groupMembersSearchUrl = "https://api.vk.com/method/groups.getMembers?group_id=%d&sort=time_desc&offset=%d&count=%d&access_token=%s";
private final static String usersGetUrl = "https://api.vk.com/method/users.get";
private final static String getFriendsUrl = "https://api.vk.com/method/friends.get?user_id=%d&access_token=%s";
private final static String joinGroupUrl = "https://api.vk.com/method/groups.join?group_id=%d&access_token=%s";
private final static String friendsAddUrl = "https://api.vk.com/method/friends.add";
private final static String wallPostWithAttachmentsUrl = "https://api.vk.com/method/wall.post";
// private final static String getWallUploadServerUrl = "https://api.vk.com/method/wall.getPhotoUploadServer?access_token=%s";
private final static String getWallUploadServerUrl = "https://api.vk.com/method/photos.getWallUploadServer?save_big=%d&access_token=%s";
// private final static String saveWallPhotoUrl = "https://api.vk.com/method/wall.savePost";
private final static String saveWallPhotoUrl = "https://api.vk.com/method/photos.saveWallPhoto";
private final static String setStatusUrl = "https://api.vk.com/method/status.set";
private final HttpClient client;
private ObjectMapper objectMapper = new ObjectMapper();
public static VKConnector createInstance(HttpClient httpClient)
{
return new VKConnectorImpl(httpClient);
}
public static VKConnector createInstance()
{
return new VKConnectorImpl(new DefaultHttpClient());
}
public String getToken(int appid, String appkey, String username, String password) throws IOException
{
String request = String.format(authUrl, appid, appkey, username, password);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode result = objectMapper.readTree(responseBody);
if (result.get("access_token") != null)
return result.get("access_token").asText();
else
return null;
}
public List<Group> searchGroups(String query, int count, String token) throws IOException
{
String request = String.format(groupsSearchUrl, URLEncoder.encode(query, "UTF-8"), 0, count, token);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode resultTree = objectMapper.readTree(responseBody);
ArrayNode arrayNode = (ArrayNode) resultTree.get("response");
List<Group> groups = new ArrayList<>();
for (int i = 1; i < arrayNode.size(); i++)
{
Group group = objectMapper.readValue(arrayNode.get(i).toString(), Group.class);
groups.add(group);
}
return groups;
}
public List<Long> getFriends(User user, String token) throws IOException
{
String request = String.format(getFriendsUrl, user.getId(), token);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode resultTree = objectMapper.readTree(responseBody);
List<Long> result = new ArrayList<>();
ArrayNode usersJsonNode = (ArrayNode) resultTree.get("response");
for (JsonNode userJsonNode : usersJsonNode)
{
result.add(userJsonNode.asLong());
}
return result;
}
public List<User> getUsers(Collection<Long> userIds, String name_case, String token) throws IOException
{
String request = usersGetUrl;
log.debug(request);
HttpPost httpPost = new HttpPost(request);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
if (userIds != null)
{
String userIdsStr = "";
for (Long userId : userIds)
{
if (!userIdsStr.isEmpty())
{
userIdsStr += ",";
}
userIdsStr += String.valueOf(userId);
}
nameValuePairs.add(new BasicNameValuePair("uids", userIdsStr));
}
nameValuePairs.add(new BasicNameValuePair("fields", "bdate,sex,city,online"));
nameValuePairs.add(new BasicNameValuePair("access_token", token));
nameValuePairs.add(new BasicNameValuePair("name_case", name_case));
log.debug(nameValuePairs);
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(httpPost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode resultTree = objectMapper.readTree(responseBody);
if (resultTree == null)
return null;
ArrayNode responseJsonNode = (ArrayNode) resultTree.get("response");
if (responseJsonNode == null)
return null;
List<User> result = new ArrayList<User>();
for (JsonNode userJsonNode : responseJsonNode)
{
User user = new User();
user.setId(userJsonNode.get("uid").asLong());
user.setFirstName(userJsonNode.get("first_name").asText());
user.setLastName(userJsonNode.get("last_name").asText());
user.setSex(userJsonNode.get("sex").asInt());
if (userJsonNode.get("bdate") != null)
{
user.setBdate(userJsonNode.get("bdate").asText());
}
if (userJsonNode.get("city") != null)
{
user.setCityId(userJsonNode.get("city").asInt());
}
user.setOnline(userJsonNode.get("online").asInt());
result.add(user);
}
return result;
}
public List<Long> getGroupMembers(long groupId, int count, String token) throws IOException
{
String request = String.format(groupMembersSearchUrl, groupId, 0, count, token);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode resultTree = objectMapper.readTree(responseBody);
JsonNode responseJsonNode = resultTree.get("response");
List<Long> result = new ArrayList<Long>();
ArrayNode usersJsonNode = (ArrayNode) responseJsonNode.get("users");
for (JsonNode userJsonNode : usersJsonNode)
{
result.add(userJsonNode.asLong());
}
return result;
}
public void joinGroup(long groupId, String token) throws IOException
{
String request = String.format(joinGroupUrl, groupId, token);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
}
public AddFriendResult addFriend(long uid, String text, Captcha captcha, String token) throws IOException
{
String request = friendsAddUrl;
log.debug(request);
HttpPost httpPost = new HttpPost(request);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("user_id", String.valueOf(uid)));
nameValuePairs.add(new BasicNameValuePair("text", text));
nameValuePairs.add(new BasicNameValuePair("access_token", token));
if (captcha != null)
{
nameValuePairs.add(new BasicNameValuePair("captcha_sid", captcha.getCaptchaSid()));
nameValuePairs.add(new BasicNameValuePair("captcha_key", captcha.getCaptchaKey()));
}
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(httpPost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
return createAddFriendResult(responseBody);
}
public WallPostResult wallPost(Long gid, Post post, Captcha captcha, String token) throws IOException
{
String request = wallPostWithAttachmentsUrl;
log.debug(request);
HttpPost httpPost = new HttpPost(request);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
if (gid != null)
{
nameValuePairs.add(new BasicNameValuePair("owner_id", String.valueOf(gid)));
}
if (post.isFromGroup())
{
nameValuePairs.add(new BasicNameValuePair("from_group", "1"));
}
nameValuePairs.add(new BasicNameValuePair("message", post.getMessage()));
if (post.getAttachments() != null)
{
nameValuePairs.add(new BasicNameValuePair("attachments", StringUtils.join(post.getAttachments(), ",")));
}
nameValuePairs.add(new BasicNameValuePair("access_token", token));
if (post.getLatitude() != null && post.getLongitude() != null
&& post.getLatitude() != 0 && post.getLongitude() != 0)
{
nameValuePairs.add(new BasicNameValuePair("lat", String.valueOf(post.getLatitude())));
nameValuePairs.add(new BasicNameValuePair("long", String.valueOf(post.getLongitude())));
}
if (captcha != null)
{
nameValuePairs.add(new BasicNameValuePair("captcha_sid", captcha.getCaptchaSid()));
nameValuePairs.add(new BasicNameValuePair("captcha_key", captcha.getCaptchaKey()));
}
log.debug(nameValuePairs);
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(httpPost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode jsonNode = objectMapper.readTree(responseBody);
WallPostResult wallPostResult = new WallPostResult();
if (jsonNode.has("error"))
{
wallPostResult.setSuccess(false);
JsonNode errorNode = jsonNode.get("error");
wallPostResult.setMessage(errorNode.get("error_msg").asText());
wallPostResult.setErrorCode(errorNode.get("error_code").asLong());
if (errorNode.has("captcha_sid"))
{
Captcha newCaptcha = new Captcha();
newCaptcha.setCaptchaSid(errorNode.get("captcha_sid").asText());
newCaptcha.setCaptchaImg(errorNode.get("captcha_img").asText());
wallPostResult.setCaptcha(newCaptcha);
}
}
else
{
wallPostResult.setSuccess(true);
wallPostResult.setPostId(jsonNode.get("response").get("post_id").asLong());
}
return wallPostResult;
}
@Override
public String uploadWallPhoto(String token, byte[] bytes) throws IOException, InterruptedException
{
String myWallUploadServer = getMyWallUploadServer(token);
UploadedPhoto uploadedPhoto = uploadPhoto(myWallUploadServer, bytes);
//TODO: Thread.sleep(5000) may be needed
return saveMyWallPhoto(uploadedPhoto, token);
}
public AddFriendResult setStatus(String text, String token) throws IOException
{
String request = setStatusUrl;
log.debug(request);
HttpPost httpPost = new HttpPost(request);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("access_token", token));
nameValuePairs.add(new BasicNameValuePair("text", text));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(httpPost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
return createAddFriendResult(responseBody);
}
private VKConnectorImpl(HttpClient httpClient)
{
this.client = httpClient;
}
private AddFriendResult createAddFriendResult(String responseBody) throws IOException
{
JsonNode resultTree = objectMapper.readTree(responseBody);
AddFriendResult addFriendResult = new AddFriendResult();
if (resultTree.has("error"))
{
addFriendResult.setSuccess(false);
JsonNode errorNode = resultTree.get("error");
addFriendResult.setMessage(errorNode.get("error_msg").asText());
addFriendResult.setErrorCode(errorNode.get("error_code").asLong());
if (errorNode.has("captcha_sid"))
{
Captcha newCaptcha = new Captcha();
newCaptcha.setCaptchaSid(errorNode.get("captcha_sid").asText());
newCaptcha.setCaptchaImg(errorNode.get("captcha_img").asText());
addFriendResult.setCaptcha(newCaptcha);
}
}
else
{
addFriendResult.setSuccess(true);
addFriendResult.setResult(resultTree.get("response").asInt());
}
return addFriendResult;
}
private String getMyWallUploadServer(String token) throws IOException
{
String request = String.format(getWallUploadServerUrl, 1, token);
// String request = String.format(getWallUploadServerUrl, token);
log.debug(request);
HttpGet httpGet = new HttpGet(request);
HttpResponse response = client.execute(httpGet);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
JsonNode responseJsonNode = objectMapper.readTree(responseBody);
log.debug(responseBody);
return responseJsonNode.get("response").get("upload_url").asText();
}
private UploadedPhoto uploadPhoto(String serverUrl, byte[] photo) throws IOException
{
HttpPost httppost = new HttpPost(serverUrl);
MultipartEntity mpEntity = new MultipartEntity();
ByteArrayBody byteArrayBody = new ByteArrayBody(photo, "photo.jpg");
mpEntity.addPart("photo", byteArrayBody);
httppost.setEntity(mpEntity);
HttpResponse response = client.execute(httppost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
return objectMapper.readValue(responseBody, UploadedPhoto.class);
}
private String saveMyWallPhoto(UploadedPhoto uploadedPhoto, String token) throws IOException
{
String request = saveWallPhotoUrl;
log.debug(request);
HttpPost httpPost = new HttpPost(request);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("access_token", token));
nameValuePairs.add(new BasicNameValuePair("photo", uploadedPhoto.getPhoto()));
nameValuePairs.add(new BasicNameValuePair("server", String.valueOf(uploadedPhoto.getServer())));
nameValuePairs.add(new BasicNameValuePair("hash", String.valueOf(uploadedPhoto.getHash())));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(httpPost);
String responseBody = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
log.debug(responseBody);
JsonNode responseJsonTree = objectMapper.readTree(responseBody);
return responseJsonTree.get("response").get(0).get("id").asText();
}
}