com.appspot.bitlyminous.handler.twitter.TweetForMeHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.appspot.bitlyminous.handler.twitter.TweetForMeHandler.java

Source

/*
 * Copyright 2010 Nabeel Mukhtar 
 * 
 * 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 com.appspot.bitlyminous.handler.twitter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Level;

import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.http.AccessToken;
import twitter4j.http.OAuthAuthorization;

import com.appspot.bitlyminous.constant.ApplicationConstants;
import com.appspot.bitlyminous.constant.ApplicationResources;
import com.appspot.bitlyminous.entity.Story;
import com.appspot.bitlyminous.entity.Tag;
import com.appspot.bitlyminous.entity.Tags;
import com.appspot.bitlyminous.entity.Url;
import com.appspot.bitlyminous.entity.User;
import com.appspot.bitlyminous.gateway.DeliciousGateway;
import com.appspot.bitlyminous.gateway.DiggGateway;
import com.appspot.bitlyminous.gateway.GatewayFactory;
import com.appspot.bitlyminous.service.RecommendationService;
import com.appspot.bitlyminous.service.ServiceFactory;
import com.googleapis.ajax.common.PagedList;
import com.googleapis.ajax.schema.WebResult;
import com.googleapis.ajax.services.WebSearchQuery;

/**
 * The Class TweetForMeHandler.
 */
public class TweetForMeHandler extends AbstractTwitterHandler {

    /** The Constant GATEWAY_FACTORY. */
    private static final GatewayFactory GATEWAY_FACTORY = GatewayFactory.newInstance();

    /**
     * Instantiates a new tweet for me handler.
     * 
     * @param commandName the command name
     * @param context the context
     */
    public TweetForMeHandler(String commandName, TwitterContext context) {
        super(commandName, context);
    }

    /* (non-Javadoc)
     * @see com.appspot.bitlyminous.handler.twitter.TwitterHandler#execute(twitter4j.Status)
     */
    @Override
    public StatusUpdate execute(Status tweet) {
        try {
            User user = context.getUser();
            if (user == null) {
                user = getUserByScreenName(tweet.getUser().getScreenName());
                context.setUser(user);
            }
            if (user == null || user.getTwitterToken() == null || user.getTwitterSecret() == null) {
                StatusUpdate reply = new StatusUpdate(
                        ApplicationResources.getLocalizedString("com.appspot.bitlyminous.message.notAuthenticated",
                                new String[] { "@" + tweet.getUser().getScreenName(), "Twitter",
                                        shortenUrl(ApplicationConstants.TWITTER_CALLBACK_URL) }));
                reply.setInReplyToStatusId(tweet.getId());
                return reply;
            } else {
                Twitter twitter = getTwitterClient(user.getTwitterToken().getValue(),
                        user.getTwitterSecret().getValue());
                String status = buildStatus(user.getUrls(), user.getTags());
                if (status != null) {
                    StatusUpdate reply = new StatusUpdate(status);
                    reply.setInReplyToStatusId(tweet.getId());
                    twitter.updateStatus(reply);
                }
                return null;
            }
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error while tweeting on behalf of user.", e);
        }
        return null;
    }

    /**
     * Builds the status.
     * 
     * @param urls the urls
     * @param tags the tags
     * 
     * @return the string
     */
    private String buildStatus(List<Url> urls, Tags tags) {
        if (tags != null) {
            DeliciousGateway deliciousGateway = getDeliciousGateway();
            DiggGateway diggGateway = getDiggGateway();
            urls = topUrls(urls, 3);
            List<Tag> tagList = topTags(tags.getTag(), 3);
            for (Url entity : urls) {
                WebSearchQuery googleQuery = getGoogleWebSearchQuery();
                googleQuery.withRelatedSite(entity.getUrl());
                List<Url> relatedUrls = new ArrayList<Url>();
                if (!tagList.isEmpty()) {
                    for (Tag tag : tagList) {
                        try {
                            relatedUrls.addAll(deliciousGateway.getPopularUrls(tag.getTag()));
                            relatedUrls.addAll(convertToUrls(diggGateway.getPopularStories(tag.getTag(), 5)));
                        } catch (Exception e) {
                            logger.log(Level.WARNING, "Error while getting related urls.", e);
                        }
                    }
                    relatedUrls.addAll(convertToUrls(googleQuery.withQuery(createQuery(tagList)).list()));
                    relatedUrls = getBestMatches(entity, relatedUrls, 1);
                }

                if (!relatedUrls.isEmpty()) {
                    StringBuilder builder = new StringBuilder();
                    builder.append(trimText(relatedUrls.get(0).getDescription(), 100));
                    builder.append("...");
                    builder.append(shortenUrl(relatedUrls.get(0).getUrl()));
                    return builder.toString();
                }
            }
        }

        return null;
    }

    /**
     * Top tags.
     * 
     * @param tags the tags
     * @param count the count
     * 
     * @return the list< tag>
     */
    private List<Tag> topTags(List<Tag> tags, int count) {
        Collections.sort(tags, new Comparator<Tag>() {
            @Override
            public int compare(Tag o1, Tag o2) {
                return o2.getCount().compareTo(o1.getCount());
            }
        });

        List<Tag> retValue = new ArrayList<Tag>();
        for (int i = 0; i < tags.size() && i < count; i++) {
            retValue.add(tags.get(i));
        }

        return retValue;
    }

    /**
     * Top urls.
     * 
     * @param urls the urls
     * @param count the count
     * 
     * @return the list< url>
     */
    private List<Url> topUrls(List<Url> urls, int count) {
        Collections.sort(urls, new Comparator<Url>() {
            @Override
            public int compare(Url o1, Url o2) {
                return o2.getDateSubmitted().compareTo(o1.getDateSubmitted());
            }
        });

        List<Url> retValue = new ArrayList<Url>();
        for (int i = 0; i < urls.size() && i < count; i++) {
            retValue.add(urls.get(i));
        }

        return retValue;
    }

    /**
     * Gets the twitter client.
     * 
     * @param token the token
     * @param tokenSecret the token secret
     * 
     * @return the twitter client
     */
    protected Twitter getTwitterClient(String token, String tokenSecret) {
        return new TwitterFactory().getInstance(new OAuthAuthorization(new ConfigurationBuilder().build(),
                ApplicationConstants.TWITTER_CONSUMER_KEY, ApplicationConstants.TWITTER_CONSUMER_SECRET,
                new AccessToken(token, tokenSecret)));
    }

    /**
     * Gets the best matches.
     * 
     * @param url the url
     * @param relatedUrls the related urls
     * @param count the count
     * 
     * @return the best matches
     */
    private List<Url> getBestMatches(Url url, List<Url> relatedUrls, int count) {
        RecommendationService recommendationService = ServiceFactory.newInstance().createRecommendationService();
        List<Entry<Url, Double>> urlSimilarities = recommendationService.getUrlSimilarities(url, relatedUrls);

        List<Url> similarUrls = new ArrayList<Url>();
        for (int i = 0; i < urlSimilarities.size() && i < count; i++) {
            similarUrls.add(urlSimilarities.get(i).getKey());
        }
        return similarUrls;
    }

    /**
     * Gets the delicious gateway.
     * 
     * @return the delicious gateway
     */
    protected DeliciousGateway getDeliciousGateway() {
        return GATEWAY_FACTORY.createDeliciousGateway(ApplicationConstants.DELICIOUS_CONSUMER_KEY,
                ApplicationConstants.DELICIOUS_CONSUMER_SECRET, "dummy-access-token", "dummy-token-secret");
    }

    /**
     * Gets the digg gateway.
     * 
     * @return the digg gateway
     */
    protected DiggGateway getDiggGateway() {
        return GATEWAY_FACTORY.createDiggGateway(ApplicationConstants.DIGG_CONSUMER_KEY,
                ApplicationConstants.DIGG_CONSUMER_SECRET, ApplicationConstants.DIGG_ACCESS_TOKEN,
                ApplicationConstants.DIGG_ACCESS_TOKEN_SECRET);
    }

    /**
     * Convert to urls.
     * 
     * @param results the results
     * 
     * @return the list< url>
     */
    private List<Url> convertToUrls(PagedList<WebResult> results) {
        List<Url> urls = new ArrayList<Url>();
        for (WebResult result : results) {
            Url url = new Url();
            url.setDescription(result.getTitleNoFormatting());
            url.setUrl(result.getUnescapedUrl());

            urls.add(url);
        }
        return urls;
    }

    /**
     * Convert to urls.
     * 
     * @param popularStories the popular stories
     * 
     * @return the list< url>
     */
    private List<Url> convertToUrls(List<Story> popularStories) {
        List<Url> urls = new ArrayList<Url>();
        for (Story story : popularStories) {
            Url url = new Url();
            url.setDescription(story.getDescription());
            url.setUrl(story.getLink());

            urls.add(url);
        }
        return urls;
    }

    /**
     * Creates the query.
     * 
     * @param tags the tags
     * 
     * @return the string
     */
    private String createQuery(List<Tag> tags) {
        StringBuilder builder = new StringBuilder();
        boolean first = true;
        for (Tag tag : tags) {
            if (!first) {
                builder.append(" OR ");
            }
            builder.append(tag.getTag());
            first = false;
        }
        return builder.toString();
    }
}