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

com.easilydo.sift.api.ApiManager Maven / Gradle / Ivy

The newest version!
package com.easilydo.sift.api;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.StringWriter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.BaseRequest;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.easilydo.sift.crypto.Signatory;
import com.easilydo.sift.model.Connection;
import static com.easilydo.sift.model.Connection.*;
import com.easilydo.sift.model.Domain;
import com.easilydo.sift.model.Sift;
import com.easilydo.sift.model.ShipmentStatus;

/**
 * Primary class in the Sift Java SDK; used for interacting with the sift server.
 * After constructing an instance of the class with their api and secret keys,
 * the sift developer can make sift api calls by invoking the corresponding method.
 * All apis in the Sift API docs
 * are implemented, with the exception of the Connect Tokens and Connect Emails, which are intended
 * for a front end web flow.
 * 

* This class handles all the common parameter packaging as well as request signature generation. * Any errors that occur during the api call (timeouts, http errors, etc.) * are thrown as {@link ApiException}. */ public class ApiManager { private static Logger logger = LoggerFactory.getLogger(ApiManager.class); public static final String API_ENDPOINT = "https://api.easilydo.com"; private String apiKey; private Signatory signatory; private static final ObjectMapper objectMapper = new ObjectMapper(); /** * Sole constructor * @param apiKey sift developer's api key * @param secretKey sift developer's secret key */ public ApiManager(String apiKey, String secretKey) { this.apiKey = apiKey; this.signatory = new Signatory(secretKey); } /** * Get a list of sifts for the given user * @param username username of the user to fetch sifts for * @return list of sifts in descending order of last update time */ public List listSifts(String username) { return listSifts(username, null, null, null, null); } /** * Get a list of sifts for the given user since a certain date * @param username username of the user to fetch sifts for * @param lastUpdateTime only return sifts updated since this date * @return list of sifts in descending order of last update time */ public List listSifts(String username, Date lastUpdateTime) { return listSifts(username, lastUpdateTime, null, null, null); } /** * Get a list of sifts for the given user since a certain date * @param username username of the user to fetch sifts for * @param lastUpdateTime only return sifts updated since this date * @param offset used for paging, where to start * @param limit maximum number of results to return * @return list of sifts in descending order of last update time */ public List listSifts(String username, Date lastUpdateTime, Integer offset, Integer limit) { return listSifts(username, lastUpdateTime, offset, limit, null); } /** * Get a list of sifts for the given user since a certain date * @param username username of the user to fetch sifts for * @param lastUpdateTime only return sifts updated since this date * @param offset used for paging, where to start * @param limit maximum number of results to return * @param domains if included, only sifts from the specified domain will be returned * @return list of sifts in descending order of last update time */ public List listSifts(String username, Date lastUpdateTime, Integer offset, Integer limit, Collection domains) { List sifts = new ArrayList(); String path = String.format("/v1/users/%s/sifts", username); Map params = new HashMap(); if(lastUpdateTime != null) { params.put("last_update_time", getEpochSecs(lastUpdateTime)); } if(offset != null) { params.put("offset", offset); } if(limit != null) { params.put("limit", limit); } if(domains != null && !domains.isEmpty()) { StringBuilder list = new StringBuilder(); for(Domain domain: domains) { list.append(domain.name); list.append(","); } list.deleteCharAt(list.length() - 1); params.put("domains", list.toString()); } addCommonParams("GET", path, params); JsonNode results = executeRequest(Unirest.get(API_ENDPOINT + path).queryString(params)); for(JsonNode result: results) { sifts.add(Sift.unmarshallSift(result)); } return sifts; } /** * Get a particular sift * @param username username of the user to fetch sifts for * @param siftId numeric id of the sift to be fetched * @return the sift corresponding to the provided id */ public Sift getSift(String username, long siftId) { return getSift(username, siftId, false); } /** * Get a particular sift * @param username username of the user to fetch sifts for * @param siftId numeric id of the sift to be fetched * @param includeEml boolean indicating if mime body should be returned * @return the sift corresponding to the provided id */ public Sift getSift(String username, long siftId, boolean includeEml) { String path = String.format("/v1/users/%s/sifts/%d", username, siftId); Map params = new HashMap(); if(includeEml) { params.put("include_eml", 1); } addCommonParams("GET", path, params); JsonNode result = executeRequest(Unirest.get(API_ENDPOINT + path).queryString(params)); Sift sift = Sift.unmarshallSift(result); return sift; } /** * Get the status of a discovered shipment * @param username username of the user * @param shipmentId numeric id of the sift to be fetched * @return the status of the shipment */ public ShipmentStatus getShipmentStatus(String username, long shipmentId) { String path = String.format("/v1/users/%s/shipments/%d", username, shipmentId); Map params = getCommonParams("GET", path); JsonNode results = executeRequest(Unirest.get(API_ENDPOINT + path).queryString(params)); ShipmentStatus shipmentStatus = null; if(results.size() > 0) { shipmentStatus = ShipmentStatus.getShipmentStatus(results.findValue("orderStatus").asText()); } return shipmentStatus; } /** * Register a new user * @param username username of the new user * @param locale locale of the new user * @return the numeric user id of the newly created user */ public long addUser(String username, String locale) { String path = "/v1/users"; Map params = new HashMap(); params.put("username", username); params.put("locale", locale); addCommonParams("POST", path, params); JsonNode result = executeRequest(Unirest.post(API_ENDPOINT + path).fields(params)); return result.get("user_id").asLong(); } /** * Deletes a user * @param username username of the user to delete */ public void deleteUser(String username) { String path = String.format("/v1/users/%s", username); Map params = getCommonParams("DELETE", path); JsonNode result = executeRequest(Unirest.delete(API_ENDPOINT + path).fields(params)); } /** * List a user's email connections * @param username username of the new user * @return the list of the user's connections */ public List listConnections(String username) { return listConnections(username, null, null, false); } /** * List a user's email connections * @param username username of the user whose connections are to be fetched * @param offset used for paging, where to start * @param limit maximum number of results to return * @return the list of the user's connections */ public List listConnections(String username, Integer offset, Integer limit) { return listConnections(username, null, null, false); } /** * List a user's email connections * @param username username of the user whose connections are to be fetched * @param offset used for paging, where to start * @param limit maximum number of results to return * @param includeInvalid if true, returns invalid connections. Default is false * @return the list of the user's connections */ public List listConnections(String username, Integer offset, Integer limit, boolean includeInvalid) { List conns = new ArrayList(); String path = String.format("/v1/users/%s/email_connections", username); Map params = new HashMap(); if(offset != null) { params.put("offset", offset); } if(limit != null) { params.put("limit", limit); } if(includeInvalid) { params.put("include_invalid", 1); } addCommonParams("GET", path, params); JsonNode results = executeRequest(Unirest.get(API_ENDPOINT + path).queryString(params)); for(JsonNode result: results) { conns.add(Connection.unmarshallConnection(result)); } return conns; } /** * Add a Gmail connection to the given user account * @param username username of the user * @param account email address * @param refreshToken oauth refresh token of the account * @return a generated numeric id for the connection */ public long addGmailConnection(String username, String account, String refreshToken) { Map credentials = new HashMap(); credentials.put("refresh_token", refreshToken); return addEmailConnection(username, account, EmailType.GOOGLE, credentials); } /** * Add a Yahoo connection to the given user account * @param username username of the user * @param account email address * @param refreshToken oauth refresh token of the account * @param redirectUri redirect uri of the account * @return a generated numeric id for the connection */ public long addYahooConnection(String username, String account, String refreshToken, String redirectUri) { Map credentials = new HashMap(); credentials.put("refresh_token", refreshToken); credentials.put("redirect_uri", redirectUri); return addEmailConnection(username, account, EmailType.YAHOO, credentials); } /** * Add a Microsoft Live connection to the given user account * @param username username of the user * @param account email address * @param refreshToken oauth refresh token of the account * @param redirectUri redirect uri of the account * @return a generated numeric id for the connection */ public long addLiveConnection(String username, String account, String refreshToken, String redirectUri) { Map credentials = new HashMap(); credentials.put("refresh_token", refreshToken); credentials.put("redirect_uri", redirectUri); return addEmailConnection(username, account, EmailType.LIVE, credentials); } /** * Add an imap connection to the given user account * @param username username of the user * @param account email address * @param password password for the email account * @param host imap host to connect to * @return a generated numeric id for the connection */ public long addImapConnection(String username, String account, String password, String host) { Map credentials = new HashMap(); credentials.put("password", password); credentials.put("host", host); return addEmailConnection(username, account, EmailType.IMAP, credentials); } /** * Add a Microsoft Exchange connection to the given user account. * Sift will attempt to autodiscover the host and account name * @param username username of the user * @param email email address * @param password password for the email account * @return a generated numeric id for the connection */ public long addExchangeConnection(String username, String email, String password) { return addExchangeConnection(username, email, password, null, null); } /** * Add a Microsoft Exchange connection to the given user account. * The host and account name are provided explicitly in this case * @param username username of the user * @param email email address * @param password password for the email account * @param host exchange host to connect to * @param account exchange account username * @return a generated numeric id for the connection */ public long addExchangeConnection(String username, String email, String password, String host, String account) { Map credentials = new HashMap(); credentials.put("email", email); credentials.put("password", password); if(host != null) { credentials.put("host", host); } return addEmailConnection(username, account, EmailType.EXCHANGE, credentials); } protected long addEmailConnection(String username, String account, EmailType type, Map credentials) { String path = String.format("/v1/users/%s/email_connections", username); Map params = new HashMap(credentials); params.put("account_type", type.toString()); params.put("account", account); addCommonParams("POST", path, params); JsonNode result = executeRequest(Unirest.post(API_ENDPOINT + path).fields(params)); return result.get("id").asLong(); } /** * Deletes an email connection * @param username username of the user to delete * @param connId numeric id of the email connection */ public void deleteEmailConnection(String username, long connId) { String path = String.format("/v1/users/%s/email_connections/%d", username, connId); Map params = getCommonParams("DELETE", path); JsonNode result = executeRequest(Unirest.delete(API_ENDPOINT + path).fields(params)); } /** * Extracts available domain data from the provided eml file. * @param emlFile the eml file * @return list of sifts objects with extracted data */ public List discovery(File emlFile) { try { return discovery(new FileInputStream(emlFile)); } catch(FileNotFoundException ex) { throw new RuntimeException(ex); } } /** * Extracts available domain data from the provided eml file. * @param emlStream a stream of eml data * @return list of sifts objects with extracted data */ public List discovery(InputStream emlStream) { List sifts = new ArrayList(); String path = "/v1/discovery"; Map params = new HashMap(); params.put("email", streamToString(emlStream).trim()); addCommonParams("POST", path, params); JsonNode result = executeRequest(Unirest.post(API_ENDPOINT + path).fields(params)); Iterator iter = result.elements(); while(iter.hasNext()) { sifts.add(Sift.unmarshallSift(iter.next())); } return sifts; } /** * Used to notify the Sift development team of emails that were not parsed correctly * @param emlFile the eml file * @param locale locale of the email * @param timezone timezone of the email * @return json object with 2 boolean fields: "classfied" and "extracted" */ public JsonNode feedback(File emlFile, String locale, String timezone) { try { return feedback(new FileInputStream(emlFile), locale, timezone); } catch(FileNotFoundException ex) { throw new RuntimeException(ex); } } /** * Used to notify the Sift development team of emails that were not parsed correctly * @param emlStream a stream of eml data * @param locale locale of the email * @param timezone timezone of the email * @return json object with 2 boolean fields: "classfied" and "extracted" */ public JsonNode feedback(InputStream emlStream, String locale, String timezone) { String path = "/v1/feedback"; Map params = new HashMap(); params.put("email", streamToString(emlStream).trim()); params.put("locale", locale); params.put("timezone", timezone); addCommonParams("POST", path, params); JsonNode result = executeRequest(Unirest.post(API_ENDPOINT + path).fields(params)); return result; } protected JsonNode executeRequest(BaseRequest request) { try { HttpResponse response = request.asString(); if(response.getStatus() >= 400) { String msg = String.format("Bad HTTP response from sift server. code: %d message: %s", response.getStatus(), response.getStatusText()); logger.error(msg); throw new ApiException(msg, response.getStatus()); } JsonNode root = objectMapper.readTree(response.getBody()); logger.debug(root.toString()); int code = root.get("code").asInt(); if(code >= 400) { String id = root.get("id").asText(); String msg = String.format("Json rpc error response from sift server. requestId: %s code: %d message: %s", id, code, root.get("message").asText()); logger.error(msg); throw new ApiException(msg, code, id); } return root.get("result"); } catch(IOException ioex) { logger.error("Failed to parse json response from sift server"); throw new ApiException("Failed to parse json response from sift server", ioex); } catch(UnirestException uniex) { logger.error("Exception making REST api call"); throw new ApiException("Exception making REST api call", uniex); } } protected Map getCommonParams(String method, String path) { return addCommonParams(method, path, new HashMap()); } protected Map addCommonParams(String method, String path, Map params) { params.put("api_key", apiKey); params.put("timestamp", System.currentTimeMillis() / 1000); params.put("signature", signatory.generateSignature(method, path, params)); return params; } protected static long getEpochSecs(Date date) { return date.getTime() / 1000; } protected static String streamToString(InputStream stream) { try { char[] buf = new char[1024]; InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); StringWriter writer = new StringWriter(); int numRead; while((numRead = reader.read(buf)) != -1) { writer.write(buf, 0, numRead); } reader.close(); writer.flush(); return writer.toString(); } catch(IOException ex) { throw new RuntimeException(ex); } } protected static void main(String[] args) { ApiManager apiMan = new ApiManager(args[0], args[1]); long id = apiMan.addGmailConnection("reg-test", "", ""); //long id = apiMan.addUser("reg-test", "en_US"); logger.info(String.valueOf(id)); //List sifts = apiMan.discovery(new File(args[2])); //java.util.Set domains = new java.util.HashSet<>(); //domains.add(Domain.FLIGHT);domains.add(Domain.HOTEL); //List sifts = apiMan.listSifts("carl", new Date(1535785200000L), null, null, domains); //Sift sift = apiMan.getSift("carl", 6383644L, false); //List conns = apiMan.listConnections("arl"); /* for(Connection conn: conns) { logger.info(conn.toString()); } for(Sift sift: sifts) { logger.info(sift.toString()); } */ } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy