/* * Copyright (C) 2013 Chris Lacy * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.tweetalib.android.fetch; import android.util.Log; import org.asynctasktex.AsyncTaskEx; import org.tweetalib.android.ConnectionStatus; import org.tweetalib.android.TwitterConstant; import org.tweetalib.android.TwitterContentHandle; import org.tweetalib.android.TwitterFetchResult; import org.tweetalib.android.TwitterPaging; import org.tweetalib.android.callback.TwitterFetchDirectMessagesFinishedCallback; import org.tweetalib.android.model.TwitterDirectMessages; import org.tweetalib.android.model.TwitterDirectMessages.AddUserCallback; import java.util.HashMap; import twitter4j.DirectMessage; import twitter4j.Paging; import twitter4j.ResponseList; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.User; public class TwitterFetchDirectMessages { private FetchMessagesWorkerCallbacks mCallbacks; private final HashMap<String, TwitterDirectMessages> mMessagesHashMap; private Integer mFetchMessagesCallbackHandle; private final HashMap<Integer, TwitterFetchDirectMessagesFinishedCallback> mFinishedCallbackMap; /* * */ public void clearCallbacks() { if (mFinishedCallbackMap != null) { mFinishedCallbackMap.clear(); } } public TwitterDirectMessages setDirectMessages(TwitterContentHandle contentHandle, TwitterDirectMessages messages) { TwitterDirectMessages cachedMessages = getDirectMessages(contentHandle); cachedMessages.add(messages); return cachedMessages; } /* * */ public interface FetchMessagesWorkerCallbacks { public Twitter getTwitterInstance(); public void addUser(User user); } /* * */ public TwitterFetchDirectMessages() { mFinishedCallbackMap = new HashMap<Integer, TwitterFetchDirectMessagesFinishedCallback>(); mFetchMessagesCallbackHandle = 0; mMessagesHashMap = new HashMap<String, TwitterDirectMessages>(); } /* * */ public void setWorkerCallbacks(FetchMessagesWorkerCallbacks callbacks) { mCallbacks = callbacks; } /* * */ TwitterFetchDirectMessagesFinishedCallback getFetchStatusesCallback( Integer callbackHandle) { return mFinishedCallbackMap .get(callbackHandle); } /* * */ void removeFetchStatusesCallback( TwitterFetchDirectMessagesFinishedCallback callback) { if (mFinishedCallbackMap.containsValue(callback)) { mFinishedCallbackMap.remove(callback.getHandle()); } } /* * */ Twitter getTwitterInstance() { return mCallbacks.getTwitterInstance(); } public void removeFromDirectMessageHashMap(TwitterDirectMessages mesages) { if (mMessagesHashMap != null) { for (String key : mMessagesHashMap.keySet()) { TwitterDirectMessages feed = mMessagesHashMap.get(key); feed.remove(mesages); } } } /* * */ public TwitterDirectMessages getDirectMessages( TwitterContentHandle contentHandle) { if (mMessagesHashMap != null) { TwitterDirectMessages messages = mMessagesHashMap.get(contentHandle .getKey()); if (messages == null) { String id = contentHandle.getIdentifier(); long idLong = Long.parseLong(id); messages = new TwitterDirectMessages(idLong); mMessagesHashMap.put(contentHandle.getKey(), messages); } return messages; } return null; } /* * */ public TwitterDirectMessages getDirectMessages( TwitterContentHandle contentHandle, TwitterPaging paging, TwitterFetchDirectMessagesFinishedCallback callback, ConnectionStatus connectionStatus) { if (connectionStatus != null && !connectionStatus.isOnline()) { if (callback != null) { callback.finished(contentHandle, new TwitterFetchResult(false, connectionStatus.getErrorMessageNoConnection()), null); } return null; } if (mFinishedCallbackMap.containsValue(callback)) { throw new RuntimeException("Shouldn't be"); } mFinishedCallbackMap.put(mFetchMessagesCallbackHandle, callback); new FetchStatusesTask().execute(AsyncTaskEx.PRIORITY_HIGH, "Fetch DMs", new FetchDirectMessagesTaskInput( mFetchMessagesCallbackHandle, contentHandle, paging, connectionStatus)); mFetchMessagesCallbackHandle += 1; return null; } /* * */ public void sendDirectMessage(long userId, String recipientScreenName, String statusText, TwitterContentHandle contentHandle, TwitterFetchDirectMessagesFinishedCallback callback, ConnectionStatus connectionStatus) { if (connectionStatus != null && !connectionStatus.isOnline()) { if (callback != null) { callback.finished(contentHandle, new TwitterFetchResult(false, connectionStatus.getErrorMessageNoConnection()), null); } } mFinishedCallbackMap.put(mFetchMessagesCallbackHandle, callback); new FetchStatusesTask().execute(AsyncTaskEx.PRIORITY_HIGH, "Fetch DMs", new FetchDirectMessagesTaskInput( mFetchMessagesCallbackHandle, userId, recipientScreenName, statusText, connectionStatus)); mFetchMessagesCallbackHandle += 1; } /* * */ public void cancel(TwitterFetchDirectMessagesFinishedCallback callback) { removeFetchStatusesCallback(callback); } /* * */ class FetchDirectMessagesTaskInput { FetchDirectMessagesTaskInput(Integer callbackHandle, TwitterContentHandle contentHandle, TwitterPaging paging, ConnectionStatus connectionStatus) { mCallbackHandle = callbackHandle; mContentHandle = contentHandle; mPaging = paging; mConnectionStatus = connectionStatus; } FetchDirectMessagesTaskInput(Integer callbackHandle, Long userId, String recipientScreenName, String statusText, ConnectionStatus connectionStatus) { mCallbackHandle = callbackHandle; mUserId = userId; mRecipientScreenName = recipientScreenName; mStatusText = statusText; mConnectionStatus = connectionStatus; } final Integer mCallbackHandle; Long mUserId; String mRecipientScreenName; String mStatusText; TwitterContentHandle mContentHandle; TwitterPaging mPaging; final ConnectionStatus mConnectionStatus; } /* * */ class FetchDirectMessagesTaskOutput { FetchDirectMessagesTaskOutput(TwitterContentHandle contentHandle, TwitterFetchResult result, Integer callbackHandle, TwitterDirectMessages messages) { mContentHandle = contentHandle; mResult = result; mCallbackHandle = callbackHandle; mMessages = messages; } final TwitterContentHandle mContentHandle; final TwitterFetchResult mResult; final Integer mCallbackHandle; final TwitterDirectMessages mMessages; } /* * */ class FetchStatusesTask extends AsyncTaskEx<FetchDirectMessagesTaskInput, Void, FetchDirectMessagesTaskOutput> { @Override protected FetchDirectMessagesTaskOutput doInBackground( FetchDirectMessagesTaskInput... inputArray) { Thread.currentThread().setPriority(Thread.MAX_PRIORITY); FetchDirectMessagesTaskInput input = inputArray[0]; TwitterDirectMessages messages = null; Twitter twitter = getTwitterInstance(); String errorDescription = null; if (input.mConnectionStatus != null && !input.mConnectionStatus.isOnline()) { return new FetchDirectMessagesTaskOutput(input.mContentHandle, new TwitterFetchResult(false, input.mConnectionStatus .getErrorMessageNoConnection()), input.mCallbackHandle, null); } if (twitter != null) { try { if (input.mStatusText != null) { Log.d("api-call", "sendDirectMessage"); DirectMessage dm = twitter.sendDirectMessage( input.mRecipientScreenName, input.mStatusText); messages = new TwitterDirectMessages(input.mUserId); messages.add(dm); } else { Paging defaultPaging = new Paging(1); defaultPaging.setCount(30); Paging paging; if (input.mPaging != null) { paging = input.mPaging.getT4JPaging(); } else { paging = defaultPaging; } switch (input.mContentHandle.getDirectMessagesType()) { case RECIEVED_MESSAGES: case ALL_MESSAGES: case ALL_MESSAGES_FRESH: { if (input.mContentHandle.getDirectMessagesType() == TwitterConstant.DirectMessagesType.ALL_MESSAGES_FRESH) { mMessagesHashMap.remove(input.mContentHandle.getKey()); } messages = getDirectMessages(input.mContentHandle); // Annoyingly, DMs can't be retrieved in a threaded // format. Handle this // by getting sent and received and managing // ourselves... Log.d("api-call", "getDirectMessages"); ResponseList<DirectMessage> receivedDirectMessages = twitter .getDirectMessages(paging); ResponseList<DirectMessage> sentDirectMessages = null; if (input.mContentHandle.getDirectMessagesType() == TwitterConstant.DirectMessagesType.ALL_MESSAGES || input.mContentHandle.getDirectMessagesType() == TwitterConstant.DirectMessagesType.ALL_MESSAGES_FRESH) { Log.d("api-call", "getSendDirectMessages"); sentDirectMessages = twitter .getSentDirectMessages(paging); } AddUserCallback addUserCallback = new AddUserCallback() { @Override public void addUser(User user) { mCallbacks.addUser(user); } }; messages.add(sentDirectMessages, receivedDirectMessages, addUserCallback); break; } default: break; } } } catch (TwitterException e) { e.printStackTrace(); errorDescription = e.getErrorMessage(); Log.e("api-call", errorDescription, e); if (e.getRateLimitStatus() != null && e.getRateLimitStatus().getRemaining() <= 0) { errorDescription += "\nTry again in " + e.getRateLimitStatus().getSecondsUntilReset() + " " + "seconds"; } } } return new FetchDirectMessagesTaskOutput(input.mContentHandle, new TwitterFetchResult( errorDescription == null, errorDescription), input.mCallbackHandle, messages); } @Override protected void onPostExecute(FetchDirectMessagesTaskOutput output) { TwitterFetchDirectMessagesFinishedCallback callback = getFetchStatusesCallback(output.mCallbackHandle); if (callback != null) { callback.finished(output.mContentHandle, output.mResult, output.mMessages); removeFetchStatusesCallback(callback); } super.onPostExecute(output); } } }