Java tutorial
/* * MIT License * * Copyright (c) 2016 BotMill.io * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package co.aurasphere.botmill.fb.internal.util.network; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import co.aurasphere.botmill.core.internal.util.network.BotMillNetworkResponse; import co.aurasphere.botmill.core.internal.util.network.NetworkUtils; import co.aurasphere.botmill.fb.FbBotMillContext; import co.aurasphere.botmill.fb.internal.util.json.FbBotMillJsonUtils; import co.aurasphere.botmill.fb.model.base.AttachmentType; import co.aurasphere.botmill.fb.model.incoming.FacebookConfirmationMessage; import co.aurasphere.botmill.fb.model.incoming.FacebookError; import co.aurasphere.botmill.fb.model.incoming.FacebookErrorMessage; import co.aurasphere.botmill.fb.model.userprofile.FacebookUserProfile; import co.aurasphere.botmill.fb.support.FbBotMillMonitor; /** * Class that contains methods that allows FbBotMill to communicate through the * network. * * @author Donato Rimenti * */ public class FbBotMillNetworkController { /** * The logger. */ private static final Logger logger = LoggerFactory.getLogger(FbBotMillNetworkController.class); /** * The registered monitors to the {@link FbBotMillContext}. */ private static final List<FbBotMillMonitor> registeredMonitors = FbBotMillContext.getInstance() .getRegisteredMonitors(); /** * Method used to retrieve a {@link FacebookUserProfile} from an ID using * the GET method. * * @param userId * the ID of the user to retrieve. * @return the user profile info. */ public static FacebookUserProfile getUserProfile(String userId) { String pageToken = FbBotMillContext.getInstance().getPageToken(); BotMillNetworkResponse response = NetworkUtils.get(FbBotMillNetworkConstants.FACEBOOK_BASE_URL + userId + FbBotMillNetworkConstants.USER_PROFILE_FIELDS + pageToken); FacebookUserProfile user = FbBotMillJsonUtils.fromJson(response.getResponse(), FacebookUserProfile.class); return user; } /** * POSTs a message as a JSON string to Facebook. * * @param input * the JSON data to send. */ public static void postJsonMessage(StringEntity input) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } String url = FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_MESSAGES_URL + pageToken; postInternal(url, input); } /** * POSTs a message as a JSON string to Facebook. * * @param input * the JSON data to send. */ public static void postJsonMessage(Object input) { StringEntity stringEntity = toStringEntity(input); postJsonMessage(stringEntity); } /** * POSTs a thread setting as a JSON string to Facebook. * * @param input * the JSON data to send. */ public static void postThreadSetting(StringEntity input) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } String url = FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_THREAD_SETTINGS_URL + pageToken; postInternal(url, input); } public static void postMessengerProfile(StringEntity input) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } String url = FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_MESSENGER_PROFILE + pageToken; postInternal(url, input); } /** * POSTs a thread setting as a JSON string to Facebook. * * @param input * the JSON data to send. */ public static void postThreadSetting(Object input) { StringEntity stringEntity = toStringEntity(input); postThreadSetting(stringEntity); } /** * POSTs a messenger profile as a JSON string to Facebook. * * @param input * the JSON data to send. */ public static void postMessengerProfile(Object input) { StringEntity stringEntity = toStringEntity(input); postMessengerProfile(stringEntity); } /** * Performs a POST and propagates it to the registered monitors. * * @param url * the URL where to post. * @param input * the object to send. * @return the response. */ private static BotMillNetworkResponse postInternal(String url, StringEntity input) { BotMillNetworkResponse response = NetworkUtils.post(url, input); propagateResponse(response); return response; } /** * Propagates the response to the registered {@link FbBotMillMonitor}. * * @param response * the response to propagate. */ private static void propagateResponse(BotMillNetworkResponse response) { String output = response.getResponse(); if (response.isError()) { // Parses the error message and logs it. FacebookErrorMessage errorMessage = FbBotMillJsonUtils.fromJson(output, FacebookErrorMessage.class); FacebookError error = errorMessage.getError(); logger.error("Error message from Facebook. Message: [{}], Code: [{}], Type: [{}], FbTraceID: [{}].", error.getMessage(), error.getCode(), error.getType(), error.getFbTraceId()); // Sends the callback to the registered network monitors. for (FbBotMillMonitor monitor : registeredMonitors) { monitor.onError(errorMessage); } } else { FacebookConfirmationMessage confirmationMessage = FbBotMillJsonUtils.fromJson(output, FacebookConfirmationMessage.class); logger.debug("Confirmation from Facebook. Recipient ID: [{}], Message ID: [{}], Result Message: [{}]", confirmationMessage.getRecipientId(), confirmationMessage.getMessageId(), confirmationMessage.getResult()); // Sends the callback to the registered network monitors. for (FbBotMillMonitor monitor : registeredMonitors) { monitor.onConfirmation(confirmationMessage); } } } /** * DELETEs a JSON string as a Facebook's Thread Setting. * * @param input * the JSON data to send. */ public static void deleteThreadSetting(StringEntity input) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } String url = FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_THREAD_SETTINGS_URL + pageToken; BotMillNetworkResponse response = NetworkUtils.delete(url, input); propagateResponse(response); } /** * DELETEs a JSON string as a Facebook's Thread Setting. * * @param input * the data to send. */ public static void deleteThreadSetting(Object input) { StringEntity stringEntity = toStringEntity(input); deleteThreadSetting(stringEntity); } /** * DELETEs a JSON string as a Facebook's Messenger Profile. * * @param input * the JSON data to send. */ public static void deleteMessengerProfile(StringEntity input) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } String url = FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_MESSENGER_PROFILE + pageToken; BotMillNetworkResponse response = NetworkUtils.delete(url, input); propagateResponse(response); } /** * DELETEs a JSON string as a Facebook's Messenger Profile. * * @param input * the data to send. */ public static void deleteMessengerProfile(Object input) { StringEntity stringEntity = toStringEntity(input); deleteMessengerProfile(stringEntity); } /** * Validates a Facebook Page Token. * * @param pageToken * the token to validate. * @return true if the token is not null or empty, false otherwise. */ private static boolean validatePageToken(String pageToken) { if (pageToken == null || "".equals(pageToken)) { logger.error( "FbBotMill validation error: Page token can't be null or empty! Have you called the method FbBotMillContext.getInstance().setup(String, String)?"); return false; } return true; } /** * Utility method that converts an object to its StringEntity * representation. * * @param object * the object to convert to a StringEntity. * @return a {@link StringEntity} object containing the object JSON. */ private static StringEntity toStringEntity(Object object) { StringEntity input = null; try { String json = FbBotMillJsonUtils.toJson(object); input = new StringEntity(json, "UTF-8"); input.setContentType("application/json"); logger.debug("Request: {}", inputStreamToString(input.getContent())); } catch (Exception e) { logger.error("Error during JSON message creation: ", e); } return input; } /** * Utility method which converts an InputStream to a String. * * @param stream * the InputStream to convert. * @return a String with the InputStream content. * @throws IOException * Signals that an I/O exception has occurred. */ private static String inputStreamToString(InputStream stream) throws IOException { ByteArrayOutputStream result = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; String resultString = null; while ((length = stream.read(buffer)) != -1) { result.write(buffer, 0, length); } resultString = result.toString("UTF-8"); return resultString; } // TODO: used for attaching files but not working at the moment. /** * POSTs a message as a JSON string to Facebook. * * @param recipient * the recipient * @param type * the type * @param file * the file */ public static void postFormDataMessage(String recipient, AttachmentType type, File file) { String pageToken = FbBotMillContext.getInstance().getPageToken(); // If the page token is invalid, returns. if (!validatePageToken(pageToken)) { return; } // TODO: add checks for valid attachmentTypes (FILE, AUDIO or VIDEO) HttpPost post = new HttpPost(FbBotMillNetworkConstants.FACEBOOK_BASE_URL + FbBotMillNetworkConstants.FACEBOOK_MESSAGES_URL + pageToken); FileBody filedata = new FileBody(file); StringBody recipientPart = new StringBody("{\"id\":\"" + recipient + "\"}", ContentType.MULTIPART_FORM_DATA); StringBody messagePart = new StringBody( "{\"attachment\":{\"type\":\"" + type.name().toLowerCase() + "\", \"payload\":{}}}", ContentType.MULTIPART_FORM_DATA); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.STRICT); builder.addPart("recipient", recipientPart); builder.addPart("message", messagePart); // builder.addPart("filedata", filedata); builder.addBinaryBody("filedata", file); builder.setContentType(ContentType.MULTIPART_FORM_DATA); // builder.setBoundary("----WebKitFormBoundary7MA4YWxkTrZu0gW"); HttpEntity entity = builder.build(); post.setEntity(entity); // Logs the raw JSON for debug purposes. BufferedReader br; // post.addHeader("Content-Type", "multipart/form-data"); try { // br = new BufferedReader(new InputStreamReader( // ()))); Header[] allHeaders = post.getAllHeaders(); for (Header h : allHeaders) { logger.debug("Header {} -> {}", h.getName(), h.getValue()); } // String output = br.readLine(); } catch (Exception e) { e.printStackTrace(); } // postInternal(post); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return "FbBotMillNetworkController []"; } }