package com.takefive.plugins.jira.wechat.api;
import com.atlassian.jira.util.json.JSONException;
import com.atlassian.jira.util.json.JSONObject;
import com.atlassian.sal.api.pluginsettings.PluginSettings;
import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
import com.ning.http.client.Response;
import com.takefive.plugins.jira.wechat.api.template.Department;
import com.takefive.plugins.jira.wechat.api.template.JsonSerializable;
import com.takefive.plugins.jira.wechat.api.template.Member;
import com.takefive.plugins.jira.wechat.configuration.ConfigurationAccess;
import com.takefive.plugins.jira.wechat.configuration.ConfigurationConstants;
import com.takefive.plugins.jira.wechat.util.DateUtils;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handles active WeChat connection requests (eg. sending messages).
*
* @author lafickens
*
*/
public class WeChatActiveConnection {
private static final Logger logger = LoggerFactory.getLogger(WeChatActiveConnection.class);
private final AsyncHttpClient client;
private final PluginSettingsFactory pluginSettingsFactory;
private PluginSettings pluginSettings;
private ConfigurationAccess config;
private String corpId;
private String corpSecret;
public WeChatActiveConnection(PluginSettingsFactory pluginSettingsFactory) {
client = new AsyncHttpClient();
this.pluginSettingsFactory = pluginSettingsFactory;
pluginSettings = this.pluginSettingsFactory.createGlobalSettings();
corpId = (String) pluginSettings.get("jira-wechat.corpId");
corpSecret = (String) pluginSettings.get("jira-wechat.corpSecret");
}
private JSONObject send(String url, String method, String message) throws ConnectionException {
BoundRequestBuilder b;
if (method == HttpMethods.GET)
b = client.prepareGet(url);
else if (method == HttpMethods.POST)
b = client.preparePost(url);
else if (method == HttpMethods.PUT)
b = client.preparePut(url);
else if (method == HttpMethods.DELETE)
b = client.prepareDelete(url);
else
// Wrong method type
throw new ConnectionException("Wrong method type");
// Set body if any
if (message != null)
b.setBody(message);
Future<Response> f = b.execute();
// Try connect
try {
Response r = f.get();
JSONObject responseJson = new JSONObject(r.getResponseBody());
if (responseJson.getInt("errcode") != 0) {
throw new ConnectionException("WeChat server returns error code: " + responseJson.getInt("errorcode"));
}
return responseJson;
} catch (InterruptedException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
} catch (JSONException e) {
e.printStackTrace();
throw new ConnectionException("Corrupt data");
} catch (ExecutionException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
} catch (IOException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
}
}
public String getAccessToken() throws ConnectionException {
logger.debug("Retrieving token");
// Check if token exists already and is within expiration.
String settingsAccessToken = config.getString(ConfigurationConstants.ACCESS_TOKEN);
int settingsExpiresIn = (Integer) pluginSettings.get(ConfigurationConstants.TOKEN_EXPIRATION);
if (settingsAccessToken != null && settingsExpiresIn > DateUtils.getUnixTime()) {
return settingsAccessToken;
}
// If token doesn't exist or has already expired, request a new one.
Future<Response> f = client.prepareGet(URLHelper.getAuthenticationURL(corpId, corpSecret)).execute();
try {
Response r = f.get();
JSONObject tokenJson = new JSONObject(r.getResponseBody());
if (tokenJson.has("errcode")) {
throw new ConnectionException("WeChat server returns error code: " + tokenJson.getInt("errcode"));
}
String accessToken = tokenJson.getString("access_token");
int expiresAt = tokenJson.getInt("expires_in");
pluginSettings.put("jira-wechat.accessToken", accessToken);
pluginSettings.put("jira-wechat.tokenExpiresIn", DateUtils.getUnixTime() + expiresAt);
return accessToken;
} catch (InterruptedException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
} catch (JSONException e) {
e.printStackTrace();
throw new ConnectionException("Corrupt data");
} catch (ExecutionException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
} catch (IOException e) {
e.printStackTrace();
throw new ConnectionException("Connection failure");
}
}
public void sendMessage(JsonSerializable message) throws ConnectionException {
logger.debug("Sending message");
String token = getAccessToken();
String url = URLHelper.getSendMessageURL(token);
send(url, HttpMethods.POST, message.toJson());
}
public void addMember(Member member) throws ConnectionException {
logger.debug("Adding or updating member");
String token = getAccessToken();
String url = URLHelper.getAddMemberURL(token);
send(url, HttpMethods.POST, member.toJson());
}
public void updateMember(Member member) throws ConnectionException {
logger.debug("Adding or updating member");
String token = getAccessToken();
String url = URLHelper.getUpdateMemberURL(token);
send(url, HttpMethods.POST, member.toJson());
}
public void deleteMember(String userId) throws ConnectionException {
logger.debug("Deleting member");
String token = getAccessToken();
String url = URLHelper.getDeleteMemberURL(token, userId);
send(url, HttpMethods.GET, null);
}
public void deleteMember(Member member) throws ConnectionException {
deleteMember(member.getUserId());
}
public void inviteFollow(Member member) throws ConnectionException {
logger.debug("Inviting member to follow");
String token = getAccessToken();
String url = URLHelper.getInviteFollowURL(token);
try {
String json = new JSONObject().append("userid", member.getUserId()).toString();
send(url, HttpMethods.POST, json);
} catch (JSONException e) {
// Should not happen
e.printStackTrace();
throw new ConnectionException("Shouldn't happen");
}
}
public void addDepartment(Department department) throws ConnectionException {
logger.debug("Adding or updating department");
String token = getAccessToken();
String url = URLHelper.getAddDepartmentURL(token);
send(url, HttpMethods.POST, department.toJson());
}
}