package com.instructure.canvasapi.api; import android.content.Context; import com.instructure.canvasapi.model.Conversation; import com.instructure.canvasapi.utilities.APIHelpers; import com.instructure.canvasapi.utilities.CanvasCallback; import org.json.JSONException; import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import retrofit.Callback; import retrofit.client.Response; import retrofit.http.Body; import retrofit.http.DELETE; import retrofit.http.EncodedQuery; import retrofit.http.GET; import retrofit.http.POST; import retrofit.http.PUT; import retrofit.http.Path; import retrofit.http.Query; import retrofit.mime.TypedByteArray; import retrofit.mime.TypedInput; /** * Copyright (c) 2015 Instructure. All rights reserved. */ public class ConversationAPI extends BuildInterfaceAPI { public enum ConversationScope { ALL,UNREAD,ARCHIVED,STARRED,SENT } private static String conversationScopeToString(ConversationScope scope){ if(scope == ConversationScope.UNREAD) { return "unread"; } else if (scope == ConversationScope.STARRED) { return "starred"; } else if (scope == ConversationScope.ARCHIVED) { return "archived"; } else if (scope == ConversationScope.SENT) { return "sent"; } return ""; } public enum WorkflowState {READ,UNREAD,ARCHIVED} private static String conversationStateToString(WorkflowState state){ if(state == WorkflowState.UNREAD) { return "unread"; } else if (state == WorkflowState.READ) { return "read"; } else if (state == WorkflowState.ARCHIVED) { return "archived"; } return ""; } interface ConversationsInterface { @GET("/conversations/?interleave_submissions=1") void getFirstPageConversationList(@Query("scope") String scope, Callback<Conversation[]> callback); @GET("/{next}") void getNextPageConversationList(@Path(value = "next", encode = false) String nextURL, Callback<Conversation[]>callback); @GET("/conversations/{id}/?interleave_submissions=1") void getDetailedConversation(@Path("id") long conversation_id, @Query("auto_mark_as_read") int markAsRead, Callback<Conversation> callback); @POST("/conversations/{id}/add_message") void addMessageToConversation(@Path("id")long conversation_id, @Body TypedInput message, CanvasCallback<Conversation> callback); @POST("/conversations?group_conversation=true") void createConversation(@EncodedQuery("recipients[]") String recipients, @Body TypedInput message, @Query("subject") String subject, @Query("context_code") String contextCode, @Query("bulk_message") int isGroup, CanvasCallback<Response> callback); @DELETE("/conversations/{conversationid}") void deleteConversation(@Path("conversationid")long conversationID, CanvasCallback<Response>responseCallback); @PUT("/conversations/{conversationid}?conversation[workflow_state]=unread") void markConversationAsUnread(@Path("conversationid")long conversationID, @Body String body, CanvasCallback<Response>responseCallback); @PUT("/conversations/{conversationid}?conversation[workflow_state]=archived") void archiveConversation(@Path("conversationid")long conversationID, @Body String body, CanvasCallback<Response>responseCallback); @PUT("/conversations/{conversationid}?conversation[workflow_state]=read") void unArchiveConversation(@Path("conversationid")long conversationID, @Body String body, CanvasCallback<Response>responseCallback); @PUT("/conversations/{conversationid}") void setIsStarred(@Path("conversationid")long conversationID, @Query("conversation[starred]") boolean isStarred, @Body String body, CanvasCallback<Conversation>responseCallback); @PUT("/conversations/{conversationid}") void setIsSubscribed(@Path("conversationid")long conversationID, @Query("conversation[subscribed]") boolean isSubscribed, @Body String body, CanvasCallback<Conversation>responseCallback); @PUT("/conversations/{conversationid}") void setSubject(@Path("conversationid")long conversationID, @Query("conversation[subject]") String subject, @Body String body, CanvasCallback<Conversation>responseCallback); @PUT("/conversations/{conversationid}") void setWorkflowState(@Path("conversationid")long conversationID, @Query("conversation[workflow_state]") String workflowState, @Body String body, CanvasCallback<Conversation>responseCallback); ///////////////////////////////////////////////////////////////////////////// // Synchronous ///////////////////////////////////////////////////////////////////////////// @GET("/conversations/?interleave_submissions=1") Conversation[] getFirstPageConversationList(@Query("scope") String scope, @Query("per_page") int number); @GET("/conversations/{id}/?interleave_submissions=1") Conversation getDetailedConversationSynchronous(@Path("id") long conversation_id); @POST("/conversations/{id}/add_message") Conversation addMessageToConversationSynchronous(@Path("id")long conversation_id, @Query("body")String message, @Body String body, @Query("attachment_ids[]") List<String> attachments); } ///////////////////////////////////////////////////////////////////////// // API Calls ///////////////////////////////////////////////////////////////////////// public static void getDetailedConversation(CanvasCallback<Conversation> callback, long conversation_id, boolean markAsRead) { if (APIHelpers.paramIsNull(callback)) return; buildCacheInterface(ConversationsInterface.class, callback).getDetailedConversation(conversation_id, APIHelpers.booleanToInt(markAsRead), callback); buildInterface(ConversationsInterface.class, callback).getDetailedConversation(conversation_id, APIHelpers.booleanToInt(markAsRead), callback); } public static void getFirstPageConversations(CanvasCallback<Conversation[]> callback, ConversationScope scope) { if (APIHelpers.paramIsNull(callback)) return; buildCacheInterface(ConversationsInterface.class, callback).getFirstPageConversationList(conversationScopeToString(scope), callback); buildInterface(ConversationsInterface.class, callback).getFirstPageConversationList(conversationScopeToString(scope), callback); } public static void getNextPageConversations(CanvasCallback<Conversation[]> callback, String nextURL){ if (APIHelpers.paramIsNull(callback, nextURL)) return; callback.setIsNextPage(true); buildCacheInterface(ConversationsInterface.class, callback, false).getNextPageConversationList(nextURL, callback); buildInterface(ConversationsInterface.class, callback, false).getNextPageConversationList(nextURL, callback); } public static void addMessageToConversation(CanvasCallback<Conversation> callback, long conversation_id, String message){ TypedInput typedInput = createTypedInput(message); if (APIHelpers.paramIsNull(callback, typedInput)) return; buildInterface(ConversationsInterface.class, callback, false).addMessageToConversation(conversation_id, typedInput, callback); } public static void createConversation(CanvasCallback<Response> callback, ArrayList<String> userIDs, String message, boolean isGroup, String contextId){ createConversation(callback, userIDs, message, "", contextId, isGroup); } public static void createConversation(CanvasCallback<Response> callback, ArrayList<String> userIDs, String message, String subject, String contextId, boolean isGroup){ TypedInput typedInput = createTypedInput(message); if(APIHelpers.paramIsNull(callback,userIDs, typedInput)){return;} //The message has to be sent to somebody. if(userIDs.size() == 0){return;} //Manually build the recipients string. String recipientKey = "recipients[]"; String recipientsParameter = userIDs.get(0); for(int i = 1; i < userIDs.size();i++){ recipientsParameter += "&"+recipientKey+"="+userIDs.get(i); } buildInterface(ConversationsInterface.class, callback, false).createConversation(recipientsParameter, typedInput, subject, contextId, isGroup ? 0 : 1, callback); } public static void deleteConversation(CanvasCallback<Response>responseCanvasCallback, long conversationId){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).deleteConversation(conversationId, responseCanvasCallback); } public static void markConversationAsUnread(CanvasCallback<Response>responseCanvasCallback, long conversationId){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).markConversationAsUnread(conversationId, "", responseCanvasCallback); } public static void archiveConversation(CanvasCallback<Response>responseCanvasCallback, long conversationId){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).archiveConversation(conversationId, "", responseCanvasCallback); } public static void unArchiveConversation(CanvasCallback<Response>responseCanvasCallback, long conversationId){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).unArchiveConversation(conversationId, "", responseCanvasCallback); } public static void subscribeToConversation(long conversationId, boolean isSubscribed, CanvasCallback<Conversation>responseCanvasCallback){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).setIsSubscribed(conversationId, isSubscribed, "", responseCanvasCallback); } public static void starConversation(long conversationId, boolean isStarred, CanvasCallback<Conversation>responseCanvasCallback){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).setIsStarred(conversationId, isStarred, "", responseCanvasCallback); } public static void setConversationSubject(long conversationId, String newSubject, CanvasCallback<Conversation>responseCanvasCallback){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).setSubject(conversationId, newSubject, "", responseCanvasCallback); } public static void setConversationWorkflowState(long conversationId, WorkflowState workflowState, CanvasCallback<Conversation>responseCanvasCallback){ if(APIHelpers.paramIsNull(responseCanvasCallback)){return;} buildInterface(ConversationsInterface.class, responseCanvasCallback, false).setWorkflowState(conversationId, conversationStateToString(workflowState), "", responseCanvasCallback); } ///////////////////////////////////////////////////////////////////////////// // Synchronous // // If Retrofit is unable to parse (no network for example) Synchronous calls // will throw a nullPointer exception. All synchronous calls need to be in a // try catch block. ///////////////////////////////////////////////////////////////////////////// public static Conversation[] getFirstPageConversationsSynchronous(ConversationScope scope, Context context, int numberToReturn) { try{ return buildInterface(ConversationsInterface.class, context).getFirstPageConversationList(conversationScopeToString(scope), numberToReturn); } catch (Exception E){ return null; } } public static Conversation getDetailedConversationSynchronous(Context context, long conversationId){ try { return buildInterface(ConversationsInterface.class, context).getDetailedConversationSynchronous(conversationId); } catch (Exception E){ return null; } } public static Conversation addMessageToConversationSynchronous(Context context, long conversationId, String messageBody, List<String> attachmentIds){ if (APIHelpers.paramIsNull(context, attachmentIds, messageBody)){return null;} return buildInterface(ConversationsInterface.class, context, false).addMessageToConversationSynchronous(conversationId, messageBody, "", attachmentIds); } private static TypedInput createTypedInput(String message){ //In order to form the expected post body we must create a json string JSONObject json = new JSONObject(); try { json.put("body", message); } catch (JSONException e) { e.printStackTrace(); } //Use this json string to create a TypedByteArray using UTF-8 TypedInput in = null; try { in = new TypedByteArray("application/json", json.toString().getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return in; } }