private SingleResponse<ParcelableDirectMessage> sendDirectMessage(
      final NotificationCompat.Builder builder,
      final long accountId,
      final long recipientId,
      final String text,
      final String imageUri) {
    final Twitter twitter = TwitterAPIFactory.getTwitterInstance(this, accountId, true, true);
    final TwitterUpload twitterUpload =
        TwitterAPIFactory.getTwitterInstance(this, accountId, true, true, TwitterUpload.class);
    if (twitter == null || twitterUpload == null) return SingleResponse.getInstance();
    try {
      final ParcelableDirectMessage directMessage;
      if (imageUri != null) {
        final String path = getImagePathFromUri(this, Uri.parse(imageUri));
        if (path == null) throw new FileNotFoundException();
        final BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, o);
        final File file = new File(path);
        BitmapUtils.downscaleImageIfNeeded(file, 100);
        final ContentLengthInputStream is = new ContentLengthInputStream(file);
        is.setReadListener(
            new MessageMediaUploadListener(this, mNotificationManager, builder, text));
        //                final MediaUploadResponse uploadResp = twitter.uploadMedia(file.getName(),
        // is, o.outMimeType);
        final MediaUploadResponse uploadResp = twitterUpload.uploadMedia(file);
        directMessage =
            new ParcelableDirectMessage(
                twitter.sendDirectMessage(recipientId, text, uploadResp.getId()), accountId, true);
        if (!file.delete()) {
          Log.d(LOGTAG, String.format("unable to delete %s", path));
        }
      } else {
        directMessage =
            new ParcelableDirectMessage(
                twitter.sendDirectMessage(recipientId, text), accountId, true);
      }
      Utils.setLastSeen(this, recipientId, System.currentTimeMillis());

      return SingleResponse.getInstance(directMessage);
    } catch (final IOException e) {
      return SingleResponse.getInstance(e);
    } catch (final TwitterException e) {
      return SingleResponse.getInstance(e);
    }
  }
 @Override
 public ResponseList<SavedSearch> loadInBackground() {
   final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, false);
   if (twitter == null) return null;
   try {
     return twitter.getSavedSearches();
   } catch (final TwitterException e) {
     Log.w(LOGTAG, e);
   }
   return null;
 }
 @Override
 protected List<TwitterWrapper.StatusListResponse> doInBackground(final Object... params) {
   final List<TwitterWrapper.StatusListResponse> result = new ArrayList<>();
   if (accountIds == null) return result;
   int idx = 0;
   final SharedPreferencesWrapper preferences = twitterWrapper.getPreferences();
   final Context context = twitterWrapper.getContext();
   final ErrorInfoStore errorInfoStore = twitterWrapper.getErrorInfoStore();
   final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
   for (final long accountId : accountIds) {
     final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
     if (twitter == null) continue;
     try {
       final Paging paging = new Paging();
       paging.count(loadItemLimit);
       final long maxId, sinceId;
       if (maxIds != null && maxIds[idx] > 0) {
         maxId = maxIds[idx];
         paging.maxId(maxId);
       } else {
         maxId = -1;
       }
       if (sinceIds != null && sinceIds[idx] > 0) {
         sinceId = sinceIds[idx];
         paging.sinceId(sinceId - 1);
         if (maxIds == null || sinceIds[idx] <= 0) {
           paging.setLatestResults(true);
         }
       } else {
         sinceId = -1;
       }
       final List<org.mariotaku.twidere.api.twitter.model.Status> statuses =
           getStatuses(twitter, paging);
       TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
       storeStatus(accountId, statuses, sinceId, maxId, true, loadItemLimit);
       publishProgress(new TwitterWrapper.StatusListResponse(accountId, statuses));
       errorInfoStore.remove(getErrorInfoKey(), accountId);
     } catch (final TwitterException e) {
       if (BuildConfig.DEBUG) {
         Log.w(LOGTAG, e);
       }
       if (e.isCausedByNetworkIssue()) {
         errorInfoStore.put(getErrorInfoKey(), accountId, ErrorInfoStore.CODE_NETWORK_ERROR);
       }
       result.add(new TwitterWrapper.StatusListResponse(accountId, e));
     }
     idx++;
   }
   return result;
 }
  private List<SingleResponse<ParcelableStatus>> updateStatus(
      final Builder builder, final ParcelableStatusUpdate statusUpdate) {
    final ArrayList<ContentValues> hashTagValues = new ArrayList<>();
    final Collection<String> hashTags = extractor.extractHashtags(statusUpdate.text);
    for (final String hashTag : hashTags) {
      final ContentValues values = new ContentValues();
      values.put(CachedHashtags.NAME, hashTag);
      hashTagValues.add(values);
    }
    final boolean hasEasterEggTriggerText = statusUpdate.text.contains(EASTER_EGG_TRIGGER_TEXT);
    final boolean hasEasterEggRestoreText =
        statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART1)
            && statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART2)
            && statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART3);
    boolean mentionedHondaJOJO = false, notReplyToOther = false;
    mResolver.bulkInsert(
        CachedHashtags.CONTENT_URI, hashTagValues.toArray(new ContentValues[hashTagValues.size()]));

    final List<SingleResponse<ParcelableStatus>> results = new ArrayList<>();

    if (statusUpdate.accounts.length == 0) return Collections.emptyList();

    try {
      if (mUseUploader && mUploader == null) throw new UploaderNotFoundException(this);
      if (mUseShortener && mShortener == null) throw new ShortenerNotFoundException(this);

      final boolean hasMedia = statusUpdate.media != null && statusUpdate.media.length > 0;

      final String overrideStatusText;
      if (mUseUploader && mUploader != null && hasMedia) {
        final MediaUploadResult uploadResult;
        try {
          mUploader.waitForService();
          uploadResult =
              mUploader.upload(
                  statusUpdate, UploaderMediaItem.getFromStatusUpdate(this, statusUpdate));
        } catch (final Exception e) {
          throw new UploadException(this);
        } finally {
          mUploader.unbindService();
        }
        if (mUseUploader && hasMedia && uploadResult == null) throw new UploadException(this);
        if (uploadResult.error_code != 0) throw new UploadException(uploadResult.error_message);
        overrideStatusText = getImageUploadStatus(this, uploadResult.media_uris, statusUpdate.text);
      } else {
        overrideStatusText = null;
      }

      final String unShortenedText =
          isEmpty(overrideStatusText) ? statusUpdate.text : overrideStatusText;

      final boolean shouldShorten =
          mValidator.getTweetLength(unShortenedText) > mValidator.getMaxTweetLength();
      final String shortenedText;
      if (shouldShorten) {
        if (mUseShortener) {
          final StatusShortenResult shortenedResult;
          mShortener.waitForService();
          try {
            shortenedResult = mShortener.shorten(statusUpdate, unShortenedText);
          } catch (final Exception e) {
            throw new ShortenException(this);
          } finally {
            mShortener.unbindService();
          }
          if (shortenedResult == null || shortenedResult.shortened == null)
            throw new ShortenException(this);
          shortenedText = shortenedResult.shortened;
        } else throw new StatusTooLongException(this);
      } else {
        shortenedText = unShortenedText;
      }
      if (statusUpdate.media != null) {
        for (final ParcelableMediaUpdate media : statusUpdate.media) {
          final String path = getImagePathFromUri(this, Uri.parse(media.uri));
          final File file = path != null ? new File(path) : null;
          if (!mUseUploader && file != null && file.exists()) {
            BitmapUtils.downscaleImageIfNeeded(file, 95);
          }
        }
      }
      for (final ParcelableAccount account : statusUpdate.accounts) {
        final Twitter twitter =
            TwitterAPIFactory.getTwitterInstance(this, account.account_id, true, true);
        final TwitterUpload upload =
            TwitterAPIFactory.getTwitterInstance(
                this, account.account_id, true, true, TwitterUpload.class);
        final StatusUpdate status = new StatusUpdate(shortenedText);
        status.inReplyToStatusId(statusUpdate.in_reply_to_status_id);
        if (statusUpdate.location != null) {
          status.location(ParcelableLocation.toGeoLocation(statusUpdate.location));
        }
        if (!mUseUploader && hasMedia) {
          final BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          final long[] mediaIds = new long[statusUpdate.media.length];
          ContentLengthInputStream is = null;
          try {
            for (int i = 0, j = mediaIds.length; i < j; i++) {
              final ParcelableMediaUpdate media = statusUpdate.media[i];
              final String path = getImagePathFromUri(this, Uri.parse(media.uri));
              if (path == null) throw new FileNotFoundException();
              BitmapFactory.decodeFile(path, o);
              final File file = new File(path);
              is = new ContentLengthInputStream(file);
              is.setReadListener(
                  new StatusMediaUploadListener(this, mNotificationManager, builder, statusUpdate));
              final ContentType contentType;
              if (TextUtils.isEmpty(o.outMimeType)) {
                contentType = ContentType.parse("image/*");
              } else {
                contentType = ContentType.parse(o.outMimeType);
              }
              final MediaUploadResponse uploadResp =
                  upload.uploadMedia(
                      new FileTypedData(is, file.getName(), file.length(), contentType));
              mediaIds[i] = uploadResp.getId();
            }
          } catch (final FileNotFoundException e) {
            Log.w(LOGTAG, e);
          } catch (final TwitterException e) {
            final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
            results.add(response);
            continue;
          } finally {
            IoUtils.closeSilently(is);
          }
          status.mediaIds(mediaIds);
        }
        status.possiblySensitive(statusUpdate.is_possibly_sensitive);

        if (twitter == null) {
          results.add(SingleResponse.<ParcelableStatus>getInstance(new NullPointerException()));
          continue;
        }
        try {
          final Status resultStatus = twitter.updateStatus(status);
          if (!mentionedHondaJOJO) {
            final UserMentionEntity[] entities = resultStatus.getUserMentionEntities();
            if (entities == null || entities.length == 0) {
              mentionedHondaJOJO = statusUpdate.text.contains("@" + HONDAJOJO_SCREEN_NAME);
            } else if (entities.length == 1 && entities[0].getId() == HONDAJOJO_ID) {
              mentionedHondaJOJO = true;
            }
            Utils.setLastSeen(this, entities, System.currentTimeMillis());
          }
          if (!notReplyToOther) {
            final long inReplyToUserId = resultStatus.getInReplyToUserId();
            if (inReplyToUserId <= 0 || inReplyToUserId == HONDAJOJO_ID) {
              notReplyToOther = true;
            }
          }
          final ParcelableStatus result =
              new ParcelableStatus(resultStatus, account.account_id, false);
          results.add(SingleResponse.getInstance(result));
        } catch (final TwitterException e) {
          final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
          results.add(response);
        }
      }
    } catch (final UpdateStatusException e) {
      final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
      results.add(response);
    }
    if (mentionedHondaJOJO) {
      triggerEasterEgg(notReplyToOther, hasEasterEggTriggerText, hasEasterEggRestoreText);
    }
    return results;
  }