Package com.google.wave.extensions.tweety

Source Code of com.google.wave.extensions.tweety.TweetyServlet

package com.google.wave.extensions.tweety;

import com.google.wave.api.AbstractRobotServlet;
import com.google.wave.api.Annotation;
import com.google.wave.api.Blip;
import com.google.wave.api.Event;
import com.google.wave.api.EventType;
import com.google.wave.api.Gadget;
import com.google.wave.api.GadgetView;
import com.google.wave.api.Range;
import com.google.wave.api.RobotMessageBundle;
import com.google.wave.api.TextView;
import com.google.wave.api.Wavelet;
import com.google.wave.api.oauth.impl.PopupLoginFormHandler;
import com.google.wave.api.oauth.impl.SingletonPersistenceManagerFactory;
import com.google.wave.extensions.tweety.controller.FetchController;
import com.google.wave.extensions.tweety.controller.SearchController;
import com.google.wave.extensions.tweety.controller.TimelineController;
import com.google.wave.extensions.tweety.model.Tweet;
import com.google.wave.extensions.tweety.model.TwitterWave;

import org.json.JSONException;

import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.cache.CacheException;
import javax.jdo.PersistenceManager;

/**
* The main servlet for Tweety robot. This robot currently supports two mode:
* <ul>
* <li>Timeline Mode: Where the robot will fetch and display the user and his
* friend's timeline.</li>
* <li>Search Mode: Where the robot will perform a Twitter search based on the
* given search term.</li>
* </ul>
*
* @author mprasetya@google.com (Marcel Prasetya)
* @author kimwhite@google.com (Kimberly White)
*/
public class TweetyServlet extends AbstractRobotServlet {

  /**
   * Key for the popup gadget's state.
   */
  private static final String GADGET_STATE = "popupClosed";

  /**
   * The key of a link annotation.
   */
  private static final String LINK_ANNOTATION_KEY = "link/manual";

  private static final Logger LOG = Logger.getLogger(TweetyServlet.class.getName());

  /**
   * The key of a tweet id annotation.
   */
  private static final String TWEET_ID_ANNOTATION_KEY = "tweetid";
 
  /**
   * The participant id of this robot.
   */
  private static final String TWEETY_ID = "tweety-wave@appspot.com";

  /**
   * A regular expression that matches a URL. The robot uses this regular
   * expression to find and linkify URL.
   */
  private static final String URL_REGEX =
      "(http://|https://)[a-zA-Z_0-9\\-]+(\\.\\w[a-zA-Z_0-9\\-]+)+(/[#&\\n\\-=?\\+\\%/\\.\\w]+)?";

  /**
   * Appends a tweet as a blip to the the given {@link Wavelet}.
   *
   * @param wavelet The {@link Wavelet} to append the tweet to.
   * @param tweet The tweet to be appended.
   */
  private void appendTweet(Wavelet wavelet, Tweet tweet) {
    // Set the metadata: author, creation time, and tweet id annotation.
    TextView textView = wavelet.appendBlip().getDocument();
    textView.setAuthor(tweet.getAuthor() + "@" + getRobotAddress());
    textView.setCreationTime(tweet.getTime());
    textView.setAnnotation(TWEET_ID_ANNOTATION_KEY, tweet.getId());

    String content = tweet.getText();
    textView.insert(0, content);

    // Linkify the content.
    Matcher matcher = Pattern.compile(URL_REGEX).matcher(content);
    while (matcher.find()) {
      textView.setAnnotation(new Range(matcher.start(), matcher.end()), LINK_ANNOTATION_KEY,
          matcher.group());
    }
  }

  /**
   * Appends a list of tweets as blips to the given {@link Wavelet}.
   *
   * @param wavelet The {@link Wavelet} to append the tweets to.
   * @param tweets The tweets to be appended.
   */
  protected void appendTweets(Wavelet wavelet, List<Tweet> tweets) {
    for (int i = tweets.size() - 1; i >= 0; --i) {
      appendTweet(wavelet, tweets.get(i));
    }
  }

  @Override
  protected String getRobotAddress() {
    return "tweety-wave.appspot.com";
  }

  @Override
  public void processEvents(RobotMessageBundle robotMessageBundle) {

    final Wavelet wavelet = robotMessageBundle.getWavelet();
    final Blip rootBlip = wavelet.getRootBlip();
    // Construct an oauthService with the user key and Twitter OAuth info.
    final String authUserId = wavelet.getCreator() + "@" + wavelet.getWaveId();
    final TwitterService twitterService = new TwitterService(authUserId, getRobotAddress());
    final PopupLoginFormHandler loginForm = new PopupLoginFormHandler(getRobotAddress());
       
    // Handle the flow when Tweety was just added to a new wave.
    if (robotMessageBundle.wasSelfAdded()) {
      rootBlip.getDocument().setAuthor(TWEETY_ID);
      wavelet.setTitle("Sign into Twitter");

      // Checks if the user is authorized with the service provider.
      // If not, fetches the request token and authorizes it.
      if (!twitterService.checkAuthorization(wavelet, loginForm)) {
        LOG.info("Request token fetched and authorized");
        return;
      }
    }
   
    PersistenceManager pm = SingletonPersistenceManagerFactory.get().getPersistenceManager();
    TwitterWave twitterWave =
        TwitterWave.getTwitterWave(pm, wavelet.getWaveId(), wavelet.getWaveletId(), wavelet
            .getCreator());

    try {
      // When user logs in via the popup, finish OAuth by exchanging
      // request token for an access token.
      for (Event event : robotMessageBundle.getEvents()) {
        if (event.getType() == EventType.DOCUMENT_CHANGED) {
          // Get all the gadgets in the wave (typically only be one).
          TextView document = wavelet.getRootBlip().getDocument();
          GadgetView gadgetView = document.getGadgetView();
          for (Gadget gadget : gadgetView.getGadgets()) {
            if ((gadget != null) && ("true".equals(gadget.getField(GADGET_STATE)))) {
              if (twitterService.checkAuthorization(wavelet, loginForm)) {
                FetchController controller =
                    twitterWave.isInSearchMode() ? new SearchController(twitterService, rootBlip,
                        twitterWave, robotMessageBundle.getEvents()) : new TimelineController(
                        twitterService, rootBlip, twitterWave, robotMessageBundle.getEvents());

                // Fetch and append tweets.
                appendTweets(wavelet, controller.fetch());

                // Clear the login form and render the search or update form.
                controller.renderForm();
              }
            }
          }
        }
       
        if (event.getType() == EventType.FORM_BUTTON_CLICKED ||
            event.getType() == EventType.BLIP_SUBMITTED) {
          // Handle the normal flow after logging in.
          FetchController controller =
              twitterWave.isInSearchMode() ? new SearchController(twitterService, rootBlip,
                  twitterWave, robotMessageBundle.getEvents()) : new TimelineController(
                  twitterService, rootBlip, twitterWave, robotMessageBundle.getEvents());

          // Fetch tweets when search or update button is clicked.
          if (controller.isButtonClicked()) {
            appendTweets(wavelet, controller.execute());
          }

          // Handle blip submitted events, that are considered as
          // @replies.
          for (Event blipSubmittedEvent : robotMessageBundle.getBlipSubmittedEvents()) {
            tweetBlipContent(twitterService, blipSubmittedEvent.getBlip(), twitterWave);
          }
        }
      }
    } catch (IOException e) {
      LOG.warning("There is a problem connecting to Twitter. Cause:" + e.getMessage());
    } catch (JSONException e) {
      LOG.warning("There is a problem parsing response from Twitter. Cause:" + e.getMessage());
    } catch (ParseException e) {
      LOG.warning("There is a problem parsing datetime response from Twitter. Cause:"
          + e.getMessage());
    } catch (CacheException e) {
      LOG.warning("There is a problem parsing response from Twitter. Cause:" + e.getMessage());
    }

    pm.makePersistent(twitterWave);
    pm.close();
  }

  /**
   * Tweets the given blip.
   *
   * @param blip The blip which content will be submitted to Twitter.
   * @param twitterWave The Twitter Wave that submitted the blip.
   * @throws IOException If there is a problem connecting to Twitter.
   * @throws JSONException If there is a problem parsing the JSON response.
   * @throws ParseException If there is a problem parsing the date in the JSON
   *         response.
   * @throws CacheException If there is a problem fetching data from Google App
   *         Engine Memcache.
   */
  private void tweetBlipContent(TwitterService service, Blip blip, TwitterWave twitterWave)
      throws CacheException, IOException, JSONException, ParseException {
    // Don't tweet changes to the root blip.
    if (blip.getBlipId() != null && blip.getBlipId().equals(blip.getWavelet().getRootBlipId())) {
      return;
    }

    String content = blip.getDocument().getText();

    // If the parent blip is a tweet, set the parent tweet id and prepend
    // the content with @<author>.
    Blip parent = blip.getParent();
    String parentTweetId = null;
    List<Annotation> annotations = parent.getDocument().getAnnotations(TWEET_ID_ANNOTATION_KEY);
    if (!annotations.isEmpty()) {
      parentTweetId = annotations.get(0).getValue();
      String author = parent.getDocument().getAuthor();
      if (author != null) {
        content = "@" + author.substring(0, author.indexOf("@")) + " " + content;
      }
    }

    // Submit the tweet to Twitter.
    service.tweet(content, parentTweetId, blip.getWavelet().getWaveId());
  }
}
TOP

Related Classes of com.google.wave.extensions.tweety.TweetyServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.