All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fluximpl.TwitterActionImpl Maven / Gradle / Ivy

package fluximpl;

import flux.*;
import flux.logging.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TwitterApi;
import org.scribe.model.*;
import org.scribe.oauth.OAuthService;
import org.scribe.utils.StreamUtils;
import org.scribe.utils.URLUtils;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Implementation for TwitterAction.
 *
 * @author [email protected]
 */
public class TwitterActionImpl extends ActionImpl implements TwitterAction {
  private static final String ACTION_VARIABLE = "TWITTER_ACTION_VARIABLE";
  private static final String AUTHORIZE_URL = "https://twitter.com/oauth/authorize";
  private static final String SEARCH_URL = "http://search.twitter.com/search.json";

  public TwitterActionImpl() {
    super(new FlowChartImpl(), "Twitter Action");
  }

  public TwitterActionImpl(FlowChartImpl fc, String name) {
    super(fc, name);
  }

  public Set getHiddenVariableNames() {
    // The returned raw type is a Set of String.
    @SuppressWarnings("unchecked")
    Set set = super.getHiddenVariableNames();
    set.add(ACTION_VARIABLE);
    return set;
  }


  public String getConsumerKey() {
    return getVariable().consumerKey;
  }

  @Override
  public void setConsumerKey(String apiKey) {
    TwitterVariable var = getVariable();
    var.consumerKey = apiKey;
    putVariable(var);
  }

  public int getCount() {
    return getVariable().count;
  }

  @Override
  public void setCount(int count) {
    TwitterVariable var = getVariable();
    var.count = count;
    putVariable(var);
  }

  public int getPage() {
    return getVariable().page;
  }

  @Override
  public void setPage(int page) {
    TwitterVariable var = getVariable();
    var.page = page;
    putVariable(var);
  }

  public String getConsumerSecret() {
    return getVariable().consumerSecret;
  }

  public Properties getParameters() {
    return getVariable().parameters;
  }

  @Override
  public void setParameters(Properties parameters) {
    TwitterVariable var = getVariable();
    var.parameters = parameters;
    putVariable(var);
  }

  public StringMapEntry getIndexedParameters(int index) {
    Properties bodyProperties = getVariable().parameters;
    return BodyPropertiesHelper.getIndexedBodyProperties(index, bodyProperties);
  }

  public StringMapEntry[] getIndexedParameters() {
    Properties queryParams = getVariable().parameters;
    return BodyPropertiesHelper.getIndexedBodyProperties(queryParams);
  }

  public void setIndexedParameters(StringMapEntry[] queryParameters) throws EngineException {
    TwitterVariable var = getVariable();
    Properties variableQueryParameters = var.parameters;
    BodyPropertiesHelper.setIndexedBodyProperties(queryParameters, variableQueryParameters);
    putVariable(var);
  }

  public void setIndexedParameters(int index, StringMapEntry arg) throws EngineException {
    TwitterVariable var = getVariable();
    Properties queryParams = var.parameters;
    BodyPropertiesHelper.setIndexedBodyProperties(index, arg, queryParams);
    putVariable(var);
  }

  @Override
  public void setConsumerSecret(String apiSecret) {
    TwitterVariable var = getVariable();
    var.consumerSecret = apiSecret;
    putVariable(var);
  }

  public boolean getOAuthEnabled() {
    return getVariable().oAuthEnabled;
  }

  @Override
  public void setOAuthEnabled(boolean oAuthEnabled) {
    TwitterVariable var = getVariable();
    var.oAuthEnabled = oAuthEnabled;
    putVariable(var);
  }

  public String getSearchQuery() {
    return getVariable().searchQuery;
  }

  @Override
  public void setSearchQuery(String searchQuery) {
    TwitterVariable var = getVariable();
    var.searchQuery = searchQuery;
    putVariable(var);
  }

  public RestActionType getRequestMethod() {
    return RestActionType.valueOf(getVariable().requestMethod);
  }

  @Override
  public void setRequestMethod(RestActionType actionType) {
    TwitterVariable var = getVariable();
    var.requestMethod = actionType.toString();
    putVariable(var);
  }

  public String getResourceUrl() {
    return getVariable().resourceUrl;
  }

  @Override
  public void setResourceUrl(String resourceUrl) {
    TwitterVariable var = getVariable();
    var.resourceUrl = resourceUrl;
    putVariable(var);
  }

  public String getUsername() {
    return getVariable().username;
  }

  @Override
  public void setUsername(String username) {
    TwitterVariable var = getVariable();
    var.username = username;
    putVariable(var);
  }

  public String getPassword() {
    Password password = getVariable().password;
    if (password != null) {
      return password.getEncryptedPassword();
    }
    return null;
  }

  @Override
  public void setPassword(String password) {
    TwitterVariable var = getVariable();
    if (password != null) {
      var.password = Password.makePassword(password);
    }
    putVariable(var);
  }

  private boolean isSearchRequest() {
    return getResourceUrl().equals(SEARCH_URL) && getRequestMethod().equals(RestActionType.GET);
  }

  @Override
  public Object execute(FlowContext flowContext) throws Exception {
    TwitterActionResult result;
    if (getOAuthEnabled()) {
      result = processOAuthRequest(flowContext);
    } else {
      Map queryParams = new HashMap();
      if (isSearchRequest()) {
        queryParams.put("q", getSearchQuery());
        queryParams.put("rpp", Integer.toString(getCount()));
        queryParams.put("page", Integer.toString(getPage()));
        result = processRequest(flowContext, queryParams);
      } else {
        queryParams.clear();
        queryParams.put("count", Integer.toString(getCount()));
        queryParams.put("page", Integer.toString(getPage()));
        result = processRequest(flowContext, queryParams);
      }
    }
    if (!StringUtil.isNullOrEmpty(result.response))
      flowContext.sendToAuditTrail("CustomEvent", result.response);
    return result;
  }

  private TwitterActionResult processRequest(FlowContext flowContext, Map queryParams) throws EngineException {
    Logger log = flowContext.getLogger();
    TwitterActionResult result = new TwitterActionResult();
    HttpURLConnection connection = null;
    try {
      connection = (HttpURLConnection) new URL(getResourceUrl()).openConnection();
      connection.setRequestMethod(getRequestMethod().name());
      String content = URLUtils.formURLEncodeMap(queryParams);
      connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
      connection.setDoOutput(true);
      connection.getOutputStream().write(content.getBytes());
      connection.connect();
      int code = connection.getResponseCode();
      String body = StreamUtils.getStreamContents(connection.getInputStream());
      result.responseCode = code;
      result.response = body;
    } catch (Exception e) {
      log.severe("Failed to process request. " + e.getMessage());
    } finally {
      if (connection != null)
        connection.disconnect();
    }
    return result;
  }

  private TwitterActionResult processOAuthRequest(FlowContext flowContext) throws EngineException {
    Logger log = flowContext.getLogger();
    OAuthService service = new ServiceBuilder()
      .provider(TwitterApi.class)
      .apiKey(getConsumerKey())
      .apiSecret(getConsumerSecret())
      .build();

    Token requestToken = service.getRequestToken();
    String oauthToken = requestToken.getToken();
    TwitterActionResult result = new TwitterActionResult();
    HttpURLConnection connection = null;
    try {
      //Authorize Step1: GET
      connection = (HttpURLConnection) new URL(AUTHORIZE_URL).openConnection();
      connection.setRequestMethod(Verb.GET.name());
      Map bodyParams = new HashMap();
      bodyParams.put("oauth_token", oauthToken);
      String content = URLUtils.formURLEncodeMap(bodyParams);
      connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
      connection.setDoOutput(true);
      connection.getOutputStream().write(content.getBytes());
      // Perform Authorization using oauth_token
      connection.connect();
      int code = connection.getResponseCode();
      log.info("Authorize GET Response code : " + code);
      String body = StreamUtils.getStreamContents(connection.getInputStream());
      log.finest("Authorize POST Response body : " + body);
      String authenticityToken = getAuthenticityTokenFromTwitterResponse(body);
      if (StringUtil.isNullOrEmpty(authenticityToken)) {
        throw new EngineException("Error in authorizing consumer.");
      }
      //Authorize Step2: POST
      connection = (HttpURLConnection) new URL(AUTHORIZE_URL).openConnection();
      connection.setRequestMethod(Verb.POST.name());
      bodyParams = new HashMap();
      bodyParams.put("authenticity_token", authenticityToken);
      bodyParams.put("oauth_token", oauthToken);
      String password = getVariable().password.getClearTextPassword();
      bodyParams.put("session[password]", password);
      bodyParams.put("session[username_or_email]", getUsername());
      content = URLUtils.formURLEncodeMap(bodyParams);
      connection.setRequestProperty("Content-Length", String.valueOf(content.getBytes().length));
      connection.setDoOutput(true);
      connection.getOutputStream().write(content.getBytes());
      // Perform Authorize using authenticity_token, oauth_token, username, password
      connection.connect();
      code = connection.getResponseCode();
      log.info("Authorize POST Response code : " + code);
      body = StreamUtils.getStreamContents(connection.getInputStream());
      log.finest("Authorize POST Response body : " + body);
      String pin = getPinFromTwitterResponse(body, log);
      Verifier verifier = new Verifier(pin);
      //Retrieve accessToken using verifier PIN.
      Token accessToken = service.getAccessToken(requestToken, verifier);
      String endpoint = null;
      Map queryParams = null;
      if (getRequestMethod().equals(RestActionType.GET)) {
        queryParams = new HashMap();
        queryParams.put("count", Integer.toString(getCount()));
        queryParams.put("page", Integer.toString(getPage()));
        endpoint = getResourceUrl()+"?"+URLUtils.formURLEncodeMap(queryParams);
      } else if (getRequestMethod().equals(RestActionType.POST)) {
        queryParams = new HashMap();
        for (Map.Entry entry : getParameters().entrySet()) {
          queryParams.put((String)entry.getKey(), (String)entry.getValue());
        }
        endpoint = getResourceUrl();
      }
      OAuthRequest request = new OAuthRequest(Verb.valueOf(getRequestMethod().name()), endpoint);
      request.getBodyParams().putAll(queryParams);
      service.signRequest(accessToken, request);
      Response response = request.send();
      log.info("Response body : " + response.getBody());
      result.responseCode = code;
      result.response = response.getBody();
    } catch (IOException e) {
      throw new EngineException("Error opening connection. Reason: " + e.getMessage());
    } finally {
      if (connection != null)
        connection.disconnect();
    }
    return result;
  }

  /**
   * Parses HTML response and fetches the authenticity token from Twitter.
   * A hacky way, but it works.
   *
   * @param html HTML response returned by Twitter.
   * @return authenticity token from Twitter.
   */
  private String getAuthenticityTokenFromTwitterResponse(String html) {
    Document document = Jsoup.parse(html, "UTF-8");
    Element element = document.body();
    element = element.select("div.clearfix").select("form input:eq(0)").first();
    return element.attr("value");
  }

  /**
   * Parses HTML response and fetches the verifier PIN from Twitter.
   * A hacky way, but works as long as Twitter response format remains same.
   *
   * @param html HTML response returned by Twitter.
   * @return verifier PIN from Twitter.
   */
  private String getPinFromTwitterResponse(String html, Logger log) throws EngineException {
    Document document = Jsoup.parse(html, "UTF-8");
    Element element = document.body();
    log.info("Response from Twitter : " + element.text());
    try {
      element = element.select("div.message-content").first().getElementById("oauth_pin");
    } catch (NullPointerException e) {
      throw new EngineException("Error retrieving consumer PIN.");
    }
    return element.text();
  }

  @Override
  public void verify() throws EngineException {
    if (StringUtil.isNullOrEmpty(getRequestMethod().name())) {
      throw new EngineException("Expected \"Request method\" to be non-null or non-empty, but it was null or empty.");
    } // if
    if (getPage() < 0 || getCount() < 0) {
      throw new EngineException("Invalid page number or count.");
    }
    if (StringUtil.isNullOrEmpty(getResourceUrl())) {
      throw new EngineException("Expected \"Resource URL\" to be non-null or non-empty, but it was null or empty.");
    } // if
    if (isSearchRequest() && StringUtil.isNullOrEmpty(getSearchQuery())) {
      throw new EngineException("Expected \"Search query\" to be non-null or non-empty, but it was null or empty.");
    } // if
    if (getOAuthEnabled()) {
      if (StringUtil.isNullOrEmpty(getConsumerKey())) {
        throw new EngineException("Expected \"Consumer Key\" to be non-null or non-empty, but it was null or empty.");
      } // if
      if (StringUtil.isNullOrEmpty(getConsumerSecret())) {
        throw new EngineException("Expected \"Consumer Secret\" to be non-null or non-empty, but it was null or empty.");
      } // if
      if (StringUtil.isNullOrEmpty(getUsername())) {
        throw new EngineException("Expected \"Username\" to be non-null or non-empty, but it was null or empty.");
      } // if
      if (StringUtil.isNullOrEmpty(getPassword())) {
        throw new EngineException("Expected \"Password\" to be non-null or non-empty, but it was null or empty.");
      } // if
    }
  }

  private TwitterVariable getVariable() {
    if (!getVariableManager().contains(ACTION_VARIABLE)) {
      getVariableManager().put(ACTION_VARIABLE, new TwitterVariable());
    }
    return (TwitterVariable) getVariableManager().get(ACTION_VARIABLE);
  }

  private void putVariable(TwitterVariable variable) {
    getVariableManager().put(ACTION_VARIABLE, variable);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy