diff --git a/twitter4j-core/src/main/java/twitter4j/FilterQuery.java b/twitter4j-core/src/main/java/twitter4j/FilterQuery.java index f3d4885e7..417dc7fc4 100644 --- a/twitter4j-core/src/main/java/twitter4j/FilterQuery.java +++ b/twitter4j-core/src/main/java/twitter4j/FilterQuery.java @@ -40,6 +40,8 @@ public final class FilterQuery implements java.io.Serializable { private int[] follow; private String[] track; private double[][] locations; + private boolean includeEntities; + /** * Creates a new FilterQuery */ @@ -132,6 +134,16 @@ public FilterQuery locations(double[][] locations){ return this; } + /** + * Set whether to include extracted entities in the stream. + * @param include True if entities should be included, else false. + * @return this instance + */ + public FilterQuery setIncludeEntities(boolean include) { + includeEntities = include; + return this; + } + /*package*/ HttpParameter[] asHttpParameterArray(){ ArrayList params = new ArrayList(); @@ -148,6 +160,9 @@ public FilterQuery locations(double[][] locations){ params.add(new HttpParameter("locations" , toLocationsString(locations))); } + if (includeEntities) { + params.add(new HttpParameter("include_entities", true)); + } HttpParameter[] paramArray = new HttpParameter[params.size()]; return params.toArray(paramArray); diff --git a/twitter4j-core/src/main/java/twitter4j/Status.java b/twitter4j-core/src/main/java/twitter4j/Status.java index e321051ed..382580a53 100644 --- a/twitter4j-core/src/main/java/twitter4j/Status.java +++ b/twitter4j-core/src/main/java/twitter4j/Status.java @@ -26,6 +26,7 @@ */ package twitter4j; +import java.net.URL; import java.util.Date; /** @@ -144,4 +145,42 @@ public interface Status extends Comparable, TwitterResponse, java.io.Ser * @since Twitter4J 2.1.2 */ String[] getContributors(); + + /** + * Returns the number of times this tweet has been retweeted, or -1 when the tweet was + * created before this feature was enabled. + * + * @return the retweet count. + */ + long getRetweetCount(); + + /** + * Returns true if the authenticating user has retweeted this tweet, or false when the tweet was + * created before this feature was enabled. + * + * @return whether the authenticating user has retweeted this tweet. + */ + boolean wasRetweetedByMe(); + + /** + * Returns an array of users mentioned in the tweet, or null if no users were mentioned. + * Note that these users only have data for ID, screen name, and name. + * + * @return An array of users mentioned in the tweet. + */ + User[] getUserMentions(); + + /** + * Returns an array of URLs mentioned in the tweet, or null if no URLs were mentioned. + * + * @return An array of URLs mentioned in the tweet. + */ + URL[] getURLs(); + + /** + * Returns an array of hashtags mentioned in the tweet, or null if no hashtags were mentioned. + * + * @return An array of users mentioned in the tweet. + */ + String[] getHashtags(); } diff --git a/twitter4j-core/src/main/java/twitter4j/StatusJSONImpl.java b/twitter4j-core/src/main/java/twitter4j/StatusJSONImpl.java index ea88e31a3..7a2ca5160 100644 --- a/twitter4j-core/src/main/java/twitter4j/StatusJSONImpl.java +++ b/twitter4j-core/src/main/java/twitter4j/StatusJSONImpl.java @@ -31,6 +31,8 @@ import twitter4j.internal.org.json.JSONException; import twitter4j.internal.org.json.JSONObject; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Arrays; import java.util.Date; @@ -57,10 +59,16 @@ private String inReplyToScreenName; private GeoLocation geoLocation = null; private Place place = null; + private long retweetCount; + private boolean wasRetweetedByMe; private String[] contributors; private Status retweetedStatus; + private User[] userMentions; + private URL[] urls; + private String[] hashtags; + private static final long serialVersionUID = 1608000492860584608L; /*package*/StatusJSONImpl(HttpResponse res) throws TwitterException { @@ -83,6 +91,8 @@ private void init(JSONObject json) throws TwitterException { inReplyToUserId = getInt("in_reply_to_user_id", json); isFavorited = getBoolean("favorited", json); inReplyToScreenName = getUnescapedString("in_reply_to_screen_name", json); + retweetCount = getLong("retweet_count", json); + wasRetweetedByMe = getBoolean("retweeted", json); try { if (!json.isNull("user")) { user = new UserJSONImpl(json.getJSONObject("user")); @@ -116,6 +126,34 @@ private void init(JSONObject json) throws TwitterException { } else{ contributors = null; } + if (!json.isNull("entities")) { + try { + JSONObject entities = json.getJSONObject("entities"); + + JSONArray userMentionsArray = entities.getJSONArray("user_mentions"); + userMentions = new User[userMentionsArray.length()]; + for(int i=0;i createStatusList(HttpResponse res) throws TwitterException { try { JSONArray list = res.asJSONArray(); diff --git a/twitter4j-core/src/main/java/twitter4j/Twitter.java b/twitter4j-core/src/main/java/twitter4j/Twitter.java index b6fc82928..4f2015b4c 100644 --- a/twitter4j-core/src/main/java/twitter4j/Twitter.java +++ b/twitter4j-core/src/main/java/twitter4j/Twitter.java @@ -321,7 +321,8 @@ public ResponseList getUserTimeline(String screenName, Paging paging) return StatusJSONImpl.createStatusList(http.get(conf.getRestBaseURL() + "statuses/user_timeline.json", mergeParameters(new HttpParameter[]{new HttpParameter("screen_name", screenName) - , new HttpParameter("include_rts", "true")} + , new HttpParameter("include_rts", "true") + , new HttpParameter("include_entities", "true")} , paging.asPostParameterArray()), auth)); } @@ -333,7 +334,8 @@ public ResponseList getUserTimeline(int userId, Paging paging) return StatusJSONImpl.createStatusList(http.get(conf.getRestBaseURL() + "statuses/user_timeline.json", mergeParameters(new HttpParameter[]{new HttpParameter("user_id", userId) - , new HttpParameter("include_rts", "true")} + , new HttpParameter("include_rts", "true") + , new HttpParameter("include_entities", "true")} , paging.asPostParameterArray()), auth)); } @@ -485,7 +487,9 @@ public IDs getRetweetedByIDs(long statusId, Paging paging) throws TwitterExcepti * {@inheritDoc} */ public Status showStatus(long id) throws TwitterException { - return new StatusJSONImpl(http.get(conf.getRestBaseURL() + "statuses/show/" + id + ".json", auth)); + return new StatusJSONImpl(http.get(conf.getRestBaseURL() + "statuses/show/" + id + ".json", + new HttpParameter[] { new HttpParameter("include_entities", "true") }, + auth)); } /** diff --git a/twitter4j-core/src/main/java/twitter4j/User.java b/twitter4j-core/src/main/java/twitter4j/User.java index 79918de65..83a64d4a2 100644 --- a/twitter4j-core/src/main/java/twitter4j/User.java +++ b/twitter4j-core/src/main/java/twitter4j/User.java @@ -222,4 +222,20 @@ public interface User extends Comparable, TwitterResponse, java.io.Seriali boolean isVerified(); boolean isFollowing(); + + /** + * Returns the number of public lists the user is listed on, or -1 + * if the count is unavailable. + * + * @return the number of public lists the user is listed on. + */ + int getListedCount(); + + /** + * Returns true if the authenticating user has requested to follow this user, + * otherwise false. + * + * @return true if the authenticating user has requested to follow this user. + */ + boolean isFollowRequestSent(); } \ No newline at end of file diff --git a/twitter4j-core/src/main/java/twitter4j/UserJSONImpl.java b/twitter4j-core/src/main/java/twitter4j/UserJSONImpl.java index 07175b3ef..e0991853a 100644 --- a/twitter4j-core/src/main/java/twitter4j/UserJSONImpl.java +++ b/twitter4j-core/src/main/java/twitter4j/UserJSONImpl.java @@ -73,6 +73,8 @@ private boolean isGeoEnabled; private boolean isVerified; private boolean isFollowing; + private int listedCount; + private boolean isFollowRequestSent; private static final long serialVersionUID = -6345893237975349030L; /*package*/UserJSONImpl(HttpResponse res) throws TwitterException { @@ -115,6 +117,8 @@ private void init(JSONObject json) throws TwitterException { profileBackgroundTiled = getBoolean("profile_background_tile", json); lang = getRawString("lang", json); statusesCount = getInt("statuses_count", json); + listedCount = getInt("listed_count", json); + isFollowRequestSent = getBoolean("follow_request_sent", json); if (!json.isNull("status")) { JSONObject statusJSON = json.getJSONObject("status"); status = new StatusJSONImpl(statusJSON); @@ -393,6 +397,20 @@ public boolean isFollowing() { return isFollowing; } + /** + * {@inheritDoc} + */ + public int getListedCount() { + return listedCount; + } + + /** + * {@inheritDoc} + */ + public boolean isFollowRequestSent() { + return isFollowRequestSent; + } + /*package*/ static PagableResponseList createPagableUserList(HttpResponse res) throws TwitterException { try { JSONObject json = res.asJSONObject(); diff --git a/twitter4j-core/src/test/java/twitter4j/StreamAPITest.java b/twitter4j-core/src/test/java/twitter4j/StreamAPITest.java index 56814583b..91b70256d 100644 --- a/twitter4j-core/src/test/java/twitter4j/StreamAPITest.java +++ b/twitter4j-core/src/test/java/twitter4j/StreamAPITest.java @@ -166,6 +166,26 @@ public void testFilterTrackPush() throws Exception { twitterStream.cleanup(); } + public void testFilterIncludesEntities() throws Exception { + this.ex = null; + + FilterQuery query = new FilterQuery(0, null, new String[]{"http", "#", "@"}); + query.setIncludeEntities(true); + twitterStream.filter(query); + + boolean sawURL, sawMention, sawHashtag; + do { + waitForStatus(); + sawURL = status.getURLs().length > 0; + sawMention = status.getUserMentions().length > 0; + sawHashtag = status.getHashtags().length > 0; + } while (!sawURL || !sawMention || !sawHashtag); + + assertNull(ex); + + twitterStream.cleanup(); + } + public void onFriendList(int[] friendIds) { System.out.println("onFriendList"); this.friendIds = friendIds; diff --git a/twitter4j-core/src/test/java/twitter4j/TwitterTestUnit.java b/twitter4j-core/src/test/java/twitter4j/TwitterTestUnit.java index ec3532a5a..2bd222a32 100644 --- a/twitter4j-core/src/test/java/twitter4j/TwitterTestUnit.java +++ b/twitter4j-core/src/test/java/twitter4j/TwitterTestUnit.java @@ -27,6 +27,7 @@ package twitter4j; import java.io.File; +import java.net.URL; import java.util.Date; import java.util.List; import static twitter4j.DAOTest.*; @@ -124,6 +125,9 @@ public void testShowUser() throws Exception { assertFalse(user.isStatusFavorited()); assertNull(user.getStatusInReplyToScreenName()); + assertTrue(1 < user.getListedCount()); + assertFalse(user.isFollowRequestSent()); + //test case for TFJ-91 null pointer exception getting user detail on users with no statuses //http://yusuke.homeip.net/jira/browse/TFJ-91 unauthenticated.showUser("twit4jnoupdate"); @@ -335,7 +339,9 @@ public void testShowStatus() throws Exception { status2 = unauthenticated.showStatus(7185737372l); assertEquals("\\u5e30%u5e30 <%}& foobar",status2.getText()); - + status = twitterAPI2.showStatus(1000l); + assertTrue(-1 <= status.getRetweetCount()); + assertFalse(status.wasRetweetedByMe()); } public void testStatusMethods() throws Exception { @@ -881,4 +887,21 @@ public void testRetweetedBy() throws Exception { assertTrue(ids.getIDs().length == 1); assertEquals(ids.getIDs()[0], 5933482); } + + public void testEntities() throws Exception { + Status status = twitterAPI2.showStatus(22035985122L); + assertEquals(2, status.getUserMentions().length); + assertEquals(1, status.getURLs().length); + + User user1 = status.getUserMentions()[0]; + assertEquals(20263710, user1.getId()); + assertEquals("rabois", user1.getScreenName()); + assertEquals("Keith Rabois", user1.getName()); + assertEquals(new URL("http://j.mp/cHv0VS"), status.getURLs()[0]); + + status = twitterAPI2.showStatus(22043496385L); + assertEquals(2, status.getHashtags().length); + assertEquals("pilaf", status.getHashtags()[0]); + assertEquals("recipe", status.getHashtags()[1]); + } }