EmailTweetBuilder.java

package org.ferris.tweial.console.email;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import javax.inject.Inject;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import org.ferris.tweial.console.lang.StringDecorator;
import org.ferris.tweial.console.preferences.PreferencesHandler;
import org.ferris.tweial.console.util.PatternForYouTube;
import twitter4j.HashtagEntity;
import twitter4j.MediaEntity;
import twitter4j.MediaEntity.Variant;
import twitter4j.Status;
import twitter4j.URLEntity;
import twitter4j.UserMentionEntity;

/**
 *
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
public class EmailTweetBuilder {

    @Inject
    protected Logger log;

    @Inject
    protected PreferencesHandler preferencesHandler;

    public EmailTweet build(Status status)
    {
        EmailTweet t = new EmailTweet();

        // Retweeter name
        t.retweeterName = (status.isRetweet()) ? status.getUser().getName() : null;

        // Which status to use for the tweet
        Status s = (status.isRetweet() ? status.getRetweetedStatus() : status);

        // User
        t.user = s.getUser();

        // Id
        t.id = Long.toString(s.getId());

        // CreatedAt
        t.createdAt = (s.getCreatedAt() == null) ? null :
            new SimpleDateFormat("M/d h:mma")
            .format(s.getCreatedAt())
            .toLowerCase()
            .replace("m", "")
        ;

        // List of YouTube videos
        t.youTubeVideos = new LinkedList<>();

        // Status Text
        StringDecorator statusText = (s.getText() == null) ? new StringDecorator("") : new StringDecorator(s.getText());
        {
            // List of unique URLs to decorate/remove from the tweet text
            Set<String> urlsToRemoveFromTweetText = new HashSet<>();

            // URLs
            URLEntity[] urlEntities = s.getURLEntities();
            if (urlEntities != null) {
                for (URLEntity entity : urlEntities) {
                    String expandedUrl = entity.getExpandedURL();
                    if (s.getQuotedStatus() != null && expandedUrl.contains(String.format("%d",s.getQuotedStatus().getId()))) {
                        statusText.decorate(
                              entity.getStart(), entity.getEnd() - 1
                            , (m) -> ""
                        );
                    } else {
                        PatternForYouTube p = new PatternForYouTube(expandedUrl);
                        if (p.matches()) {
                            t.youTubeVideos.add(p.getVidId());
                        }
                        statusText.decorate(
                              entity.getStart(), entity.getEnd() - 1
                            , (m) -> String.format("<a href=\"%1$s\">%1$s</a>", expandedUrl)
                        );
                    }
                }
            }

            // Hashtags
            // https://twitter.com/search?q=%23UnlimitedScreaming
            HashtagEntity[] hashtagEntities = s.getHashtagEntities();
            if (hashtagEntities != null) {
                for (HashtagEntity entity : hashtagEntities) {
                    statusText.decorate(
                          entity.getStart(), entity.getEnd() - 1
                        , (m) -> String.format(
                              "<a href=\"https://twitter.com/search?f=tweets&vertical=default&q=%%23%1$s\">#%1$s</a>"
                            , entity.getText()
                          )
                    );
                }
            }

            // User mentions
            // https://twitter.com/farmtrukstl/
            // https://twitter.com/PTXofficial/
            UserMentionEntity[] userMentionEntities = s.getUserMentionEntities();
            if (userMentionEntities != null) {
                for (UserMentionEntity entity : userMentionEntities) {
                    statusText.decorate(
                          entity.getStart(), entity.getEnd()-1
                        , (m) -> String.format("<a href=\"https://twitter.com/%1$s\">@%1$s</a>", entity.getScreenName())
                    );
                }
            }

            // Media photos
            t.photoUrls = new LinkedList<>(); {
            MediaEntity[] mediaEntities = s.getMediaEntities();
                if (mediaEntities != null && mediaEntities.length >= 1) {
                    for (MediaEntity entity : mediaEntities) {
                        if ("photo".equalsIgnoreCase(entity.getType())) {
                            // URL of photo in tweet (possibly)
                            urlsToRemoveFromTweetText.add(entity.getURL());
                            // URL of photo
                            if (entity.getMediaURLHttps() != null && !entity.getMediaURLHttps().isEmpty()) {
                                t.photoUrls.add(entity.getMediaURLHttps());
                            }
                            else
                            if (entity.getMediaURL() != null && !entity.getMediaURL().isEmpty()) {
                                t.photoUrls.add(entity.getMediaURL());
                            }
                            else {
                                t.photoUrls.add(preferencesHandler.findPreferences().getNoImageUrl());
                            }
                        }
                    }
                }
            }

            // Media videos
            t.videoMedia = new LinkedList<>(); {
                MediaEntity[] mediaEntities = s.getMediaEntities();
                if (mediaEntities != null && mediaEntities.length >= 1) {
                    for (MediaEntity entity : mediaEntities) {
                        if ("video".equalsIgnoreCase(entity.getType())) {
                            Arrays.stream(entity.getVideoVariants())
                                .filter(v -> v.getContentType().contains("mp4"))
                                .max(Comparator.comparing(Variant::getBitrate))
                                .ifPresent( v -> {
                                        urlsToRemoveFromTweetText.add(entity.getURL());
                                        t.videoMedia.add(
                                            new EmailVideo.Builder()
                                                .poster(entity.getMediaURLHttps())
                                                .src(v.getUrl())
                                                .type(v.getContentType())
                                                .millis(entity.getVideoDurationMillis())
                                                .build()
                                        );
                                    }
                                )
                            ;
                        }
                    }
                }
            }

            // Media animated_gif
            t.animatedGifMedia = new LinkedList<>(); {
                MediaEntity[] mediaEntities = s.getMediaEntities();
                if (mediaEntities != null && mediaEntities.length >= 1) {
                    for (MediaEntity entity : mediaEntities) {
                        if ("animated_gif".equalsIgnoreCase(entity.getType())) {
                            Arrays.stream(entity.getVideoVariants())
                                .filter(v -> v.getContentType().contains("mp4"))
                                .max(Comparator.comparing(Variant::getBitrate))
                                .ifPresent( v ->
                                    t.animatedGifMedia.add(
                                        new EmailAnimatedGif.Builder()
                                            .poster(entity.getMediaURLHttps())
                                            .src(v.getUrl())
                                            .type(v.getContentType())
                                            .build()
                                    )
                                )
                            ;
                        }
                    }
                }
            }

            // Media non-photo and non-video
            t.nonPhotoMedia = new LinkedList<>(); {
                MediaEntity[] mediaEntities = s.getMediaEntities();
                if (mediaEntities != null && mediaEntities.length >= 1) {
                    for (MediaEntity entity : mediaEntities) {
                        switch (entity.getType().toLowerCase()) {
                            case "photo":
                            case "video":
                            case "animated_gif":
                                continue;
                            default:
                                t.nonPhotoMedia.add(
                                    ToStringBuilder.reflectionToString(entity)
                                );
                        }
                    }
                }
            }

            // Remove urls from tweet text;
            for (String url : urlsToRemoveFromTweetText) {
                statusText.decorate(url, l->"");
            }

            // Convert newline to Line break
            statusText.decorate("\n", l->"<br />");
        }
        t.text = statusText.toStringDecorated();

        // Quoted tweet
        t.quotedTweet = (s.getQuotedStatus() == null) ? null : this.build(s.getQuotedStatus());

        // Return
        return t;
    }
}