1 package twitter.manage;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.net.MalformedURLException;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.Date;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Properties;
17 import java.util.logging.Level;
18 import java.util.logging.Logger;
21 import twitter.log.TwitterLogManager;
22 import twitter4j.DirectMessage;
23 import twitter4j.GeoLocation;
24 import twitter4j.PagableResponseList;
25 import twitter4j.Paging;
26 import twitter4j.Place;
27 import twitter4j.Query;
28 import twitter4j.QueryResult;
29 import twitter4j.RateLimitStatus;
30 import twitter4j.Status;
31 import twitter4j.Tweet;
32 import twitter4j.Twitter;
33 import twitter4j.TwitterException;
34 import twitter4j.TwitterFactory;
35 import twitter4j.User;
36 import twitter4j.UserList;
37 import twitter4j.conf.Configuration;
38 import twitter4j.conf.ConfigurationBuilder;
39 import twitter4j.http.AccessToken;
41 public class TweetManager {
44 * DirectMessageのユーザ情報等からステータスを生成
49 private class DirectMessageUserStatus implements Status {
54 private static final long serialVersionUID = 1L;
55 // 受信したdirectMessageの情報
56 private DirectMessage message = null;
58 private User user = null;
60 public DirectMessageUserStatus(DirectMessage directMessage, User user) {
61 this.message = directMessage;
66 public String[] getContributors() {
71 public Date getCreatedAt() {
72 return message.getCreatedAt();
76 public GeoLocation getGeoLocation() {
86 public String getInReplyToScreenName() {
87 return user.getStatusInReplyToScreenName();
91 public long getInReplyToStatusId() {
92 return user.getStatusInReplyToUserId();
96 public int getInReplyToUserId() {
101 public Place getPlace() {
106 public RateLimitStatus getRateLimitStatus() {
107 return user.getRateLimitStatus();
111 public Status getRetweetedStatus() {
116 public String getSource() {
121 public String getText() {
122 return message.getText();
126 public User getUser() {
131 public boolean isFavorited() {
132 return user.isStatusFavorited();
136 public boolean isRetweet() {
141 public boolean isTruncated() {
145 public int compareTo(Status t) {
146 throw new UnsupportedOperationException("Not supported yet.");
149 private Twitter twitter = null;
150 // クライアントのConsumer Key
151 private static final String CONSUMER_KEY = "tbo5erit2M2ZzN6n8tEYcA";
152 // クライアントのConsumer Secret 外部に漏れてはいけない
153 private static final String CONSUMER_SECRET = "tODurbdySLYU1pKjtB3MQTDRBGy562dHzVf7d62mm8";
155 private String accessToken = "";
156 // secretToken 外部に漏れてはいけない
157 private String secretToken = "";
159 private static final String PROPERTIES_DIRECTORY = TweetConfiguration.PROPERTIES_DIRECTORY;
161 private static final String TWEET_INFO_FILENAME = TweetConfiguration.TWEET_INFO_FILENAME;
163 private static final String ACCOUNT_INFORMATION_FILENAME = TweetConfiguration.ACCOUNT_INFORMATION_FILENAME;
165 private final int MAX_TWEET_NUM = 99;
167 private long sinceTweetID = 0;
168 // 前回取得したmentionのtweetID
169 private long sinceMentionID = 0;
170 // 前回取得したsendDirectMessageの情報
171 private long sinceSendDirectMessageID = 0;
172 // 前回取得したdirectMessageの情報
173 private long sinceDirectMessageID = 0;
175 private Properties property = null;
177 private Properties accountProperty = null;
179 private TwitterLogManager logManager = null;
181 public TweetManager() {
182 logManager = new TwitterLogManager();
188 * @throws IOException
189 * @throws FileNotFoundException
191 public void loadProperties() throws FileNotFoundException, IOException {
192 if (property == null) {
193 this.property = new Properties();
195 property.load(new FileInputStream("./" + PROPERTIES_DIRECTORY + "/"
196 + TWEET_INFO_FILENAME));
198 String sti = this.property.getProperty("sinceTweetID");
199 /*String smi = this.property.getProperty("sinceMentionID");
200 String ssdmi = this.property.getProperty("sinceSendDirectMessageID");
201 String sdmi = this.property.getProperty("sinceDirectMessageID");*/
204 this.sinceTweetID = Long.parseLong(sti);
205 /*this.sinceMentionID = Long.parseLong(smi);
206 this.sinceSendDirectMessageID = Long.parseLong(ssdmi);
207 this.sinceDirectMessageID = Long.parseLong(sdmi);*/
208 } catch (NumberFormatException e) {
216 * @throws IOException
218 public void saveProperties() throws IOException {
220 File logDir = new File("./" + PROPERTIES_DIRECTORY);
221 if (!logDir.exists()) {
222 // ディレクトリが存在しないので作成する
223 if (logDir.mkdir() == false) {
224 throw new IOException(PROPERTIES_DIRECTORY
225 + "ディレクトリを作成できませんでした.");
228 if (property == null) {
229 this.property = new Properties();
232 this.property.setProperty("sinceTweetID", sinceTweetID + "");
233 /*this.property.setProperty("sinceMentionID", sinceMentionID + "");
234 this.property.setProperty("sinceSendDirectMessageID",
235 sinceSendDirectMessageID + "");
236 this.property.setProperty("sinceDirectMessageID", sinceDirectMessageID
239 property.store(new FileOutputStream("./" + PROPERTIES_DIRECTORY + "/"
240 + TWEET_INFO_FILENAME), null);
245 * @throws FileNotFoundException
246 * @throws IOException
248 public void loadAccountProperties() throws FileNotFoundException, IOException {
249 if (accountProperty == null) {
250 this.accountProperty = new Properties();
252 accountProperty.load(new FileInputStream("./" + PROPERTIES_DIRECTORY + "/"
253 + ACCOUNT_INFORMATION_FILENAME));
255 this.accessToken = this.accountProperty.getProperty("accessToken");
256 this.secretToken = this.accountProperty.getProperty("secretToken");
261 * @throws IOException
263 public void saveAccountProperties() throws IOException {
265 File logDir = new File("./" + PROPERTIES_DIRECTORY);
266 if (!logDir.exists()) {
267 // ディレクトリが存在しないので作成する
268 if (logDir.mkdir() == false) {
269 throw new IOException(PROPERTIES_DIRECTORY
270 + "ディレクトリを作成できませんでした.");
273 if (accountProperty == null) {
274 this.accountProperty = new Properties();
277 this.accountProperty.setProperty("accessToken", this.accessToken);
278 this.accountProperty.setProperty("secretToken", this.secretToken);
280 accountProperty.store(new FileOutputStream("./" + PROPERTIES_DIRECTORY + "/"
281 + ACCOUNT_INFORMATION_FILENAME), null);
289 * @throws TwitterException
291 public List<Status> getDirectMessages(int num) throws TwitterException {
292 List<DirectMessage> directMessages = twitter.getDirectMessages(new Paging(1, num));
294 List<Status> messageList = new LinkedList<Status>();
296 if (directMessages != null && directMessages.size() > 0) {
298 this.sinceDirectMessageID = directMessages.get(0).getId();
299 // 一番新しいtweetを一番したに持ってくる
300 for (DirectMessage message : directMessages) {
301 User user = message.getSender();
302 DirectMessageUserStatus status = new DirectMessageUserStatus(message, user);
303 messageList.add(0, status);
309 } catch (IOException e) {
320 * @throws TwitterException
322 public List<Status> getSendDirectMessages(int num) throws TwitterException {
323 List<DirectMessage> directMessages = twitter.getSentDirectMessages(new Paging(1, num));
325 List<Status> messageList = new LinkedList<Status>();
326 if (directMessages != null && directMessages.size() > 0) {
328 this.sinceSendDirectMessageID = directMessages.get(0).getId();
329 // 一番新しいtweetを一番したに持ってくる
330 for (DirectMessage message : directMessages) {
331 User user = message.getRecipient();
332 DirectMessageUserStatus status = new DirectMessageUserStatus(message, user);
333 messageList.add(0, status);
338 } catch (IOException e) {
349 * @throws TwitterException
351 public List<Status> getMentions(int num) throws TwitterException {
352 List<Status> statuses = twitter.getMentions(new Paging(1, num));
354 List<Status> tweetList = new LinkedList<Status>();
355 if (statuses != null && statuses.size() > 0) {
357 this.sinceMentionID = statuses.get(0).getId();
358 // 一番新しいtweetを一番したに持ってくる
359 for (Status status : statuses) {
360 tweetList.add(0, status);
365 } catch (IOException e) {
372 * まだ取得していないDirectMessageを取得
375 * @throws TwitterException
377 public List<Status> getNewDirectMessages() throws TwitterException {
378 if (this.sinceDirectMessageID == 0) {
379 return getDirectMessages(MAX_TWEET_NUM);
381 List<DirectMessage> directMessages = twitter.getDirectMessages(new Paging(sinceDirectMessageID));
382 // もし20件データ取得したらもっとデータがある可能性がある
383 if (directMessages.size() >= 20) {
384 List<DirectMessage> ndata = twitter.getDirectMessages(new Paging(1,
386 ndata = ndata.subList(21, ndata.size());
387 for (DirectMessage s : ndata) {
388 // すでに取得したことのあるデータだったとき
389 if (s.getId() <= sinceDirectMessageID) {
392 directMessages.add(s);
396 List<Status> messageList = new LinkedList<Status>();
397 if (directMessages != null && directMessages.size() > 0) {
399 this.sinceDirectMessageID = directMessages.get(0).getId();
400 // 一番新しいtweetを一番したに持ってくる
401 for (DirectMessage message : directMessages) {
402 Status status = message.getSender().getStatus();
403 messageList.add(0, status);
408 } catch (IOException e) {
415 * まだ取得していないSendDirectMessageを取得
418 * @throws TwitterException
420 public List<Status> getNewSendDirectMessages() throws TwitterException {
421 if (this.sinceSendDirectMessageID == 0) {
422 return getSendDirectMessages(MAX_TWEET_NUM);
424 List<DirectMessage> directMessages = twitter.getDirectMessages(new Paging(sinceSendDirectMessageID));
425 // もし20件データ取得したらもっとデータがある可能性がある
426 if (directMessages.size() >= 20) {
427 List<DirectMessage> ndata = twitter.getSentDirectMessages(new Paging(1, MAX_TWEET_NUM));
428 ndata = ndata.subList(21, ndata.size());
429 for (DirectMessage s : ndata) {
430 // すでに取得したことのあるデータだったとき
431 if (s.getId() <= sinceSendDirectMessageID) {
434 directMessages.add(s);
438 List<Status> messageList = new LinkedList<Status>();
439 if (directMessages != null && directMessages.size() > 0) {
441 this.sinceSendDirectMessageID = directMessages.get(0).getId();
442 // 一番新しいtweetを一番したに持ってくる
443 for (DirectMessage message : directMessages) {
444 Status status = message.getRecipient().getStatus();
445 messageList.add(0, status);
450 } catch (IOException e) {
457 * まだ取得していないMention情報を取得
460 * @throws TwitterException
462 public List<Status> getNewMentionData() throws TwitterException {
464 if (sinceMentionID == 0) {
465 return getMentions(MAX_TWEET_NUM);
467 // getFriendsTimelineではRetweetは表示されないので注意
468 List<Status> statuses = twitter.getMentions(new Paging(sinceMentionID));
469 // もし20件データ取得したらもっとデータがある可能性がある
470 if (statuses.size() >= 20) {
471 List<Status> ndata = twitter.getMentions(new Paging(1,
473 ndata = ndata.subList(21, ndata.size());
474 for (Status s : ndata) {
475 // すでに取得したことのあるデータだったとき
476 if (s.getId() <= sinceMentionID) {
484 List<Status> tweetList = new LinkedList<Status>();
485 if (statuses != null && statuses.size() > 0) {
487 sinceMentionID = statuses.get(0).getId();
489 // 一番新しいtweetを一番したに持ってくる
490 for (Status status : statuses) {
491 tweetList.add(0, status);
496 } catch (IOException e) {
503 * まだ取得していないtweet情報を取得
506 * @throws TwitterException
508 public List<Status> getNewTimelineData() throws TwitterException {
510 if (sinceTweetID == 0) {
511 return getTimeline(MAX_TWEET_NUM);
513 // getFriendsTimelineではRetweetは表示されないので注意
514 List<Status> statuses = twitter.getHomeTimeline(new Paging(sinceTweetID));
515 // もし20件データ取得したらもっとデータがある可能性がある
516 if (statuses.size() >= 20) {
517 List<Status> ndata = twitter.getHomeTimeline(new Paging(1,
519 ndata = ndata.subList(21, ndata.size());
520 for (Status s : ndata) {
521 // すでに取得したことのあるデータだったとき
522 if (s.getId() <= sinceTweetID) {
529 List<Status> tweetList = new LinkedList<Status>();
530 if (statuses != null && statuses.size() > 0) {
532 sinceTweetID = statuses.get(0).getId();
534 // 一番新しいtweetを一番したに持ってくる
535 for (Status status : statuses) {
536 tweetList.add(0, status);
541 for (Status s : tweetList) {
544 } catch (IOException e) {
550 } catch (IOException e) {
557 * タイムラインを取得 一番新しいツイートは要素の一番下に追加
562 * @throws TwitterException
564 public List<Status> getTimeline(int num) throws TwitterException {
565 // getFriendsTimelineではRetweetは表示されないので注意
566 List<Status> statuses = twitter.getHomeTimeline(new Paging(1, num));
568 List<Status> tweetList = new LinkedList<Status>();
569 if (statuses != null && statuses.size() > 0) {
571 sinceTweetID = statuses.get(0).getId();
573 // 一番新しいtweetを一番したに持ってくる
574 for (Status status : statuses) {
575 tweetList.add(0, status);
580 for (Status s : tweetList) {
583 } catch (IOException e) {
588 } catch (IOException e) {
600 public List<Status> getNewSearchResult(long sinceID, String searchWord) {
603 return getSearchResult(MAX_TWEET_NUM, searchWord);
606 //TODO:同じようなコードを二回書いてる.ここは修正の必要があるかも
608 Query query = new Query(searchWord);
610 query.setRpp(this.MAX_TWEET_NUM);
614 query.setSinceId(sinceID);
616 QueryResult queryResult = null;
618 queryResult = twitter.search(query);
619 } catch (TwitterException ex) {
620 Logger.getLogger(TweetManager.class.getName()).log(
621 Level.SEVERE, "Twitter searchに失敗しました", ex);
622 ex.printStackTrace();
625 List<Status> tweetList = new LinkedList<Status>();
627 if( queryResult != null ) {
628 for(Tweet tweet: queryResult.getTweets() ) {
630 SimpleUser user = new SimpleUser();
632 user.setName( tweet.getFromUser() );
633 user.setScreenName( tweet.getFromUser() );
635 user.setId( tweet.getFromUserId() );
638 user.setProfileImageURL(new URL(tweet.getProfileImageUrl()));
639 } catch (MalformedURLException ex) {
640 Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
643 SimpleStatus status = new SimpleStatus();
644 status.setCreatedAt( tweet.getCreatedAt() );
645 status.setId( tweet.getId() );
646 status.setSource( tweet.getSource() );
647 status.setText( tweet.getText() );
648 status.setUser(user);
651 tweetList.add(status);
654 //リスト逆転 一番あたらしいtweetを一番下に
655 Collections.reverse(tweetList);
662 * @param num 指定した数だけtweetを取得
663 * @param searchWord 検索したい単語
666 public List<Status> getSearchResult(int num, String searchWord) {
667 Query query = new Query(searchWord);
673 QueryResult queryResult = null;
675 queryResult = twitter.search(query);
676 } catch (TwitterException ex) {
677 Logger.getLogger(TweetManager.class.getName()).log(
678 Level.SEVERE, "Twitter searchに失敗しました", ex);
679 ex.printStackTrace();
682 List<Status> tweetList = new LinkedList<Status>();
684 if( queryResult != null ) {
685 for(Tweet tweet: queryResult.getTweets() ) {
687 SimpleUser user = new SimpleUser();
689 user.setName( tweet.getFromUser() );
690 user.setScreenName( tweet.getFromUser() );
692 user.setId( tweet.getFromUserId() );
695 user.setProfileImageURL(new URL(tweet.getProfileImageUrl()));
696 } catch (MalformedURLException ex) {
697 Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
700 SimpleStatus status = new SimpleStatus();
701 status.setCreatedAt( tweet.getCreatedAt() );
702 status.setId( tweet.getId() );
703 status.setSource( tweet.getSource() );
704 status.setText( tweet.getText() );
705 status.setUser(user);
708 tweetList.add(status);
712 //リスト逆転 一番あたらしいtweetを一番下に
713 Collections.reverse(tweetList);
720 * @param screenName nullの場合,自分自身のお気に入りを取得
722 public List<Status> getFavoritesTweet(String screenName) throws TwitterException {
723 // getFriendsTimelineではRetweetは表示されないので注意
724 List<Status> statuses = null;
725 if( screenName == null ) {
727 statuses = twitter.getFavorites();
729 statuses = twitter.getFavorites(screenName);
731 //リスト逆転 一番あたらしいtweetを一番下に
732 Collections.reverse(statuses);
741 * @throws TwitterException
743 public List<Status> getUserTimeline(int num, int userID) throws TwitterException {
744 List<Status> statuses = twitter.getUserTimeline(userID, new Paging(1, num));
747 if (statuses != null && statuses.size() > 0) {
748 Collections.reverse(statuses);
755 * 指定したユーザが保持しているリスト一覧を取得
756 * @param userScreenName
759 public List<UserList> getUserLists(String userScreenName) {
760 List<UserList> userlist = new ArrayList<UserList>();
765 PagableResponseList<UserList> list = this.twitter.getUserLists(userScreenName, cursor);
766 userlist.addAll( list );
768 if( list.hasNext() ) {
770 cursor = list.getNextCursor();
775 } catch (TwitterException ex) {
776 Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
782 * 指定したユーザをフォローしているリストを返す
783 * @param userScreenName
786 public List<UserList> getUserListSubscriptions(String userScreenName) {
787 List<UserList> userlist = new ArrayList<UserList>();
792 PagableResponseList<UserList> list = this.twitter.getUserListSubscriptions(userScreenName, cursor);
793 userlist.addAll( list );
795 if( list.hasNext() ) {
797 cursor = list.getNextCursor();
802 } catch (TwitterException ex) {
803 Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
809 * 指定したユーザが追加されているリストを返す
810 * @param userScreenName
813 public List<UserList> getUserListMemberships(String userScreenName) {
814 List<UserList> userlist = new ArrayList<UserList>();
819 PagableResponseList<UserList> list = this.twitter.getUserListMemberships(userScreenName, cursor);
820 userlist.addAll( list );
822 if( list.hasNext() ) {
824 cursor = list.getNextCursor();
829 } catch (TwitterException ex) {
830 Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
837 * @param userScreenName ユーザ名
838 * @param listID リストID
841 * @throws TwitterException
843 public List<Status> getUserListStatuses(String userScreenName, int listID, int num)
844 throws TwitterException {
845 List<Status> tweetList =
846 this.twitter.getUserListStatuses(userScreenName, listID, new Paging(1, num));
848 if( tweetList != null && tweetList.size() > 0 ) {
849 Collections.reverse(tweetList);
856 * @param userScreenName ユーザ名
857 * @param listID リストID
860 * @throws TwitterException
862 public List<Status> getNewUserListStatuses(String userScreenName, int listID, long sinceID)
863 throws TwitterException {
865 return getUserListStatuses(userScreenName, listID, MAX_TWEET_NUM);
867 List<Status> tweetList = this.twitter.getUserListStatuses(
868 userScreenName, listID, new Paging(sinceID) );
870 if( tweetList != null && tweetList.size() > 0 ) {
871 Collections.reverse(tweetList);
881 * @throws TwitterException
883 public List<Status> getNewUserTimeline(int userID, long sinceID) throws TwitterException {
886 return getUserTimeline(MAX_TWEET_NUM, userID);
889 List<Status> statuses = twitter.getUserTimeline(userID, new Paging(sinceID));
892 if (statuses != null && statuses.size() > 0) {
893 Collections.reverse(statuses);
902 public void loginTwitter() throws FileNotFoundException, IOException {
903 twitter = new TwitterFactory().getInstance();
905 loadAccountProperties();
907 twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
908 // ここにユーザのアクセストークンを入れる
909 AccessToken ac = new AccessToken(accessToken, secretToken);
910 twitter.setOAuthAccessToken(ac);
914 } catch (FileNotFoundException e) {
916 } catch (IOException e) {
926 private Configuration getTwitterConfiguration() {
927 ConfigurationBuilder confbuilder = new ConfigurationBuilder();
928 confbuilder.setOAuthConsumerKey(CONSUMER_KEY);
929 confbuilder.setOAuthConsumerSecret(CONSUMER_SECRET);
930 return confbuilder.build();
935 * 初回時アクセストークンを取得する際に利用する
938 * @throws TwitterException
940 public void getAccessToken(String username, String password) throws TwitterException {
941 //consumer key secretを設定
942 Configuration conf = this.getTwitterConfiguration();
943 twitter = new TwitterFactory(conf).getInstance(username, password);
945 AccessToken oAuthAccessToken = twitter.getOAuthAccessToken();
946 this.accessToken = oAuthAccessToken.getToken();
947 this.secretToken = oAuthAccessToken.getTokenSecret();
951 saveAccountProperties();
952 } catch (IOException ex) {
953 ex.printStackTrace();
962 public void tweet(String message) {
963 twitter4j.Status status;
965 status = twitter.updateStatus(message);
966 } catch (TwitterException e) {
975 * @param replyToStatusID
977 public void replyTweet(String message, long replyToStatusID) {
978 twitter4j.Status status;
980 status = twitter.updateStatus(message, replyToStatusID);
981 } catch (TwitterException e) {
992 * @throws TwitterException
994 public void sendDirectMessage(String screenName, String text)
995 throws TwitterException {
996 twitter.sendDirectMessage(screenName, text);
1000 * 指定したステータスIDの発言をRetweet
1003 * @throws TwitterException
1005 public void retweet(long statusID) throws TwitterException {
1006 twitter.retweetStatus(statusID);
1012 * @throws TwitterException
1014 public void createFavorite(long statusID) throws TwitterException {
1015 twitter.createFavorite(statusID);
1019 * 指定した発言のお気に入りを取り下げる
1022 public void destroyFavorite(long statusID) throws TwitterException {
1023 twitter.destroyFavorite(statusID);
1030 * @throws TwitterException
1032 public RateLimitStatus getRateLimitStatus() throws TwitterException {
1033 return twitter.getRateLimitStatus();
1040 public String getScreenName() {
1042 if (twitter != null) {
1043 return twitter.getScreenName();
1045 }catch(TwitterException e) {