OSDN Git Service

aa353a14cb769db2a5aed55fb0e48a3f1cb7a420
[nt-manager/nt-manager.git] / src / twitter / manage / TweetManager.java
1 package twitter.manage;
2
3 import java.io.File;
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;
9 import java.net.URL;
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;
19
20
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;
40
41 public class TweetManager {
42
43     /**
44      * DirectMessageのユーザ情報等からステータスを生成
45      *
46      * @author nishio
47      *
48      */
49     private class DirectMessageUserStatus implements Status {
50
51         /**
52          *
53          */
54         private static final long serialVersionUID = 1L;
55         // 受信したdirectMessageの情報
56         private DirectMessage message = null;
57         // ユーザ情報
58         private User user = null;
59
60         public DirectMessageUserStatus(DirectMessage directMessage, User user) {
61             this.message = directMessage;
62             this.user = user;
63         }
64
65         @Override
66         public String[] getContributors() {
67             return null;
68         }
69
70         @Override
71         public Date getCreatedAt() {
72             return message.getCreatedAt();
73         }
74
75         @Override
76         public GeoLocation getGeoLocation() {
77             return null;
78         }
79
80         @Override
81         public long getId() {
82             return user.getId();
83         }
84
85         @Override
86         public String getInReplyToScreenName() {
87             return user.getStatusInReplyToScreenName();
88         }
89
90         @Override
91         public long getInReplyToStatusId() {
92             return user.getStatusInReplyToUserId();
93         }
94
95         @Override
96         public int getInReplyToUserId() {
97             return 0;
98         }
99
100         @Override
101         public Place getPlace() {
102             return null;
103         }
104
105         @Override
106         public RateLimitStatus getRateLimitStatus() {
107             return user.getRateLimitStatus();
108         }
109
110         @Override
111         public Status getRetweetedStatus() {
112             return null;
113         }
114
115         @Override
116         public String getSource() {
117             return "Unknown";
118         }
119
120         @Override
121         public String getText() {
122             return message.getText();
123         }
124
125         @Override
126         public User getUser() {
127             return user;
128         }
129
130         @Override
131         public boolean isFavorited() {
132             return user.isStatusFavorited();
133         }
134
135         @Override
136         public boolean isRetweet() {
137             return false;
138         }
139
140         @Override
141         public boolean isTruncated() {
142             return false;
143         }
144
145         public int compareTo(Status t) {
146             throw new UnsupportedOperationException("Not supported yet.");
147         }
148     }
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";
154     // accessToken
155     private String accessToken = "";
156     // secretToken 外部に漏れてはいけない
157     private String secretToken = "";
158     // 設定ファイル保存ディレクトリ名
159     private static final String PROPERTIES_DIRECTORY = TweetConfiguration.PROPERTIES_DIRECTORY;
160     // 設定ファイル保存ファイル名
161     private static final String TWEET_INFO_FILENAME = TweetConfiguration.TWEET_INFO_FILENAME;
162     //アカウント情報保存ファイル名
163     private static final String ACCOUNT_INFORMATION_FILENAME = TweetConfiguration.ACCOUNT_INFORMATION_FILENAME;
164     // 一度に取得する最大のtweet数
165     private final int MAX_TWEET_NUM = 99;
166     // 前回取得したtweetの情報
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;
174     // 設定ファイル
175     private Properties property = null;
176     //アカウント設定ファイル
177     private Properties accountProperty = null;
178     // ログ保存
179     private TwitterLogManager logManager = null;
180
181     public TweetManager() {
182         logManager = new TwitterLogManager();
183     }
184
185     /**
186      * 設定ファイルを読み込む
187      *
188      * @throws IOException
189      * @throws FileNotFoundException
190      */
191     public void loadProperties() throws FileNotFoundException, IOException {
192         if (property == null) {
193             this.property = new Properties();
194         }
195         property.load(new FileInputStream("./" + PROPERTIES_DIRECTORY + "/"
196                 + TWEET_INFO_FILENAME));
197         // 設定読み込み
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");*/
202
203         try {
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) {
209             e.printStackTrace();
210         }
211     }
212
213     /**
214      * 設定ファイルを保存する
215      *
216      * @throws IOException
217      */
218     public void saveProperties() throws IOException {
219         // 設定ファイルディレクトリを作成
220         File logDir = new File("./" + PROPERTIES_DIRECTORY);
221         if (!logDir.exists()) {
222             // ディレクトリが存在しないので作成する
223             if (logDir.mkdir() == false) {
224                 throw new IOException(PROPERTIES_DIRECTORY
225                         + "ディレクトリを作成できませんでした.");
226             }
227         }
228         if (property == null) {
229             this.property = new Properties();
230         }
231         // since idを保存
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
237                 + "");*/
238         // プロパティのリストを保存
239         property.store(new FileOutputStream("./" + PROPERTIES_DIRECTORY + "/"
240                 + TWEET_INFO_FILENAME), null);
241     }
242
243     /**
244      * アカウント情報を読み込む
245      * @throws FileNotFoundException
246      * @throws IOException
247      */
248     public void loadAccountProperties() throws FileNotFoundException, IOException {
249         if (accountProperty == null) {
250             this.accountProperty = new Properties();
251         }
252         accountProperty.load(new FileInputStream("./" + PROPERTIES_DIRECTORY + "/"
253                 + ACCOUNT_INFORMATION_FILENAME));
254         // 設定読み込み
255         this.accessToken = this.accountProperty.getProperty("accessToken");
256         this.secretToken = this.accountProperty.getProperty("secretToken");
257     }
258
259     /**
260      * アカウント情報を保存する
261      * @throws IOException
262      */
263     public void saveAccountProperties() throws IOException {
264         // 設定ファイルディレクトリを作成
265         File logDir = new File("./" + PROPERTIES_DIRECTORY);
266         if (!logDir.exists()) {
267             // ディレクトリが存在しないので作成する
268             if (logDir.mkdir() == false) {
269                 throw new IOException(PROPERTIES_DIRECTORY
270                         + "ディレクトリを作成できませんでした.");
271             }
272         }
273         if (accountProperty == null) {
274             this.accountProperty = new Properties();
275         }
276         // since idを保存
277         this.accountProperty.setProperty("accessToken", this.accessToken);
278         this.accountProperty.setProperty("secretToken", this.secretToken);
279         // プロパティのリストを保存
280         accountProperty.store(new FileOutputStream("./" + PROPERTIES_DIRECTORY + "/"
281                 + ACCOUNT_INFORMATION_FILENAME), null);
282     }
283
284     /**
285      * 受信したダイレクトメッセージを取得
286      *
287      * @param num
288      * @return
289      * @throws TwitterException
290      */
291     public List<Status> getDirectMessages(int num) throws TwitterException {
292         List<DirectMessage> directMessages = twitter.getDirectMessages(new Paging(1, num));
293         // Tweetの一覧
294         List<Status> messageList = new LinkedList<Status>();
295
296         if (directMessages != null && directMessages.size() > 0) {
297             // tweetIDを保存しておく
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);
304             }
305         }
306
307         try {
308             saveProperties();
309         } catch (IOException e) {
310             e.printStackTrace();
311         }
312         return messageList;
313     }
314
315     /**
316      * 送信したダイレクトメッセージを取得
317      *
318      * @param num
319      * @return
320      * @throws TwitterException
321      */
322     public List<Status> getSendDirectMessages(int num) throws TwitterException {
323         List<DirectMessage> directMessages = twitter.getSentDirectMessages(new Paging(1, num));
324         // Tweetの一覧
325         List<Status> messageList = new LinkedList<Status>();
326         if (directMessages != null && directMessages.size() > 0) {
327             // tweetIDを保存しておく
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);
334             }
335         }
336         try {
337             saveProperties();
338         } catch (IOException e) {
339             e.printStackTrace();
340         }
341         return messageList;
342     }
343
344     /**
345      * Mentionの取得
346      *
347      * @param num
348      * @return
349      * @throws TwitterException
350      */
351     public List<Status> getMentions(int num) throws TwitterException {
352         List<Status> statuses = twitter.getMentions(new Paging(1, num));
353         // Tweetの一覧
354         List<Status> tweetList = new LinkedList<Status>();
355         if (statuses != null && statuses.size() > 0) {
356             // tweetIDを保存しておく
357             this.sinceMentionID = statuses.get(0).getId();
358             // 一番新しいtweetを一番したに持ってくる
359             for (Status status : statuses) {
360                 tweetList.add(0, status);
361             }
362         }
363         try {
364             saveProperties();
365         } catch (IOException e) {
366             e.printStackTrace();
367         }
368         return tweetList;
369     }
370
371     /**
372      * まだ取得していないDirectMessageを取得
373      *
374      * @return
375      * @throws TwitterException
376      */
377     public List<Status> getNewDirectMessages() throws TwitterException {
378         if (this.sinceDirectMessageID == 0) {
379             return getDirectMessages(MAX_TWEET_NUM);
380         }
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,
385                     MAX_TWEET_NUM));
386             ndata = ndata.subList(21, ndata.size());
387             for (DirectMessage s : ndata) {
388                 // すでに取得したことのあるデータだったとき
389                 if (s.getId() <= sinceDirectMessageID) {
390                     break;
391                 }
392                 directMessages.add(s);
393             }
394         }
395         // Tweetの一覧
396         List<Status> messageList = new LinkedList<Status>();
397         if (directMessages != null && directMessages.size() > 0) {
398             // tweetIDを保存しておく
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);
404             }
405         }
406         try {
407             saveProperties();
408         } catch (IOException e) {
409             e.printStackTrace();
410         }
411         return messageList;
412     }
413
414     /**
415      * まだ取得していないSendDirectMessageを取得
416      *
417      * @return
418      * @throws TwitterException
419      */
420     public List<Status> getNewSendDirectMessages() throws TwitterException {
421         if (this.sinceSendDirectMessageID == 0) {
422             return getSendDirectMessages(MAX_TWEET_NUM);
423         }
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) {
432                     break;
433                 }
434                 directMessages.add(s);
435             }
436         }
437         // Tweetの一覧
438         List<Status> messageList = new LinkedList<Status>();
439         if (directMessages != null && directMessages.size() > 0) {
440             // tweetIDを保存しておく
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);
446             }
447         }
448         try {
449             saveProperties();
450         } catch (IOException e) {
451             e.printStackTrace();
452         }
453         return messageList;
454     }
455
456     /**
457      * まだ取得していないMention情報を取得
458      *
459      * @return
460      * @throws TwitterException
461      */
462     public List<Status> getNewMentionData() throws TwitterException {
463         // 一度もデータを取得していないとき
464         if (sinceMentionID == 0) {
465             return getMentions(MAX_TWEET_NUM);
466         }
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,
472                     MAX_TWEET_NUM));
473             ndata = ndata.subList(21, ndata.size());
474             for (Status s : ndata) {
475                 // すでに取得したことのあるデータだったとき
476                 if (s.getId() <= sinceMentionID) {
477                     break;
478                 }
479                 statuses.add(s);
480             }
481         }
482
483         // Tweetの一覧
484         List<Status> tweetList = new LinkedList<Status>();
485         if (statuses != null && statuses.size() > 0) {
486             // tweetIDを保存しておく
487             sinceMentionID = statuses.get(0).getId();
488
489             // 一番新しいtweetを一番したに持ってくる
490             for (Status status : statuses) {
491                 tweetList.add(0, status);
492             }
493         }
494         try {
495             saveProperties();
496         } catch (IOException e) {
497             e.printStackTrace();
498         }
499         return tweetList;
500     }
501
502     /**
503      * まだ取得していないtweet情報を取得
504      *
505      * @return
506      * @throws TwitterException
507      */
508     public List<Status> getNewTimelineData() throws TwitterException {
509         // 一度もデータを取得していないとき
510         if (sinceTweetID == 0) {
511             return getTimeline(MAX_TWEET_NUM);
512         }
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,
518                     MAX_TWEET_NUM));
519             ndata = ndata.subList(21, ndata.size());
520             for (Status s : ndata) {
521                 // すでに取得したことのあるデータだったとき
522                 if (s.getId() <= sinceTweetID) {
523                     break;
524                 }
525                 statuses.add(s);
526             }
527         }
528         // Tweetの一覧
529         List<Status> tweetList = new LinkedList<Status>();
530         if (statuses != null && statuses.size() > 0) {
531             // tweetIDを保存しておく
532             sinceTweetID = statuses.get(0).getId();
533
534             // 一番新しいtweetを一番したに持ってくる
535             for (Status status : statuses) {
536                 tweetList.add(0, status);
537             }
538         }
539         // ログ保存
540         try {
541             for (Status s : tweetList) {
542                 logManager.add(s);
543             }
544         } catch (IOException e) {
545             e.printStackTrace();
546         }
547         // 設定ファイル保存
548         try {
549             saveProperties();
550         } catch (IOException e) {
551             e.printStackTrace();
552         }
553         return tweetList;
554     }
555
556     /**
557      * タイムラインを取得 一番新しいツイートは要素の一番下に追加
558      *
559      * @param num
560      *            指定した数だけtweetを取得
561      * @return
562      * @throws TwitterException
563      */
564     public List<Status> getTimeline(int num) throws TwitterException {
565         // getFriendsTimelineではRetweetは表示されないので注意
566         List<Status> statuses = twitter.getHomeTimeline(new Paging(1, num));
567         // Tweetの一覧
568         List<Status> tweetList = new LinkedList<Status>();
569         if (statuses != null && statuses.size() > 0) {
570             // tweetIDを保存しておく
571             sinceTweetID = statuses.get(0).getId();
572
573             // 一番新しいtweetを一番したに持ってくる
574             for (Status status : statuses) {
575                 tweetList.add(0, status);
576             }
577         }
578         // ログ保存
579         try {
580             for (Status s : tweetList) {
581                 logManager.add(s);
582             }
583         } catch (IOException e) {
584             e.printStackTrace();
585         }
586         try {
587             saveProperties();
588         } catch (IOException e) {
589             e.printStackTrace();
590         }
591         return tweetList;
592     }
593
594     /**
595      * 指定したワードを含むtweetを返す
596      * @param sinceID 
597      * @param searchWord
598      * @return
599      */
600     public List<Status> getNewSearchResult(long sinceID, String searchWord) {
601         // 一度もデータを取得していないとき
602         if (sinceID == 0) {
603             return getSearchResult(MAX_TWEET_NUM, searchWord);
604         }
605
606         //TODO:同じようなコードを二回書いてる.ここは修正の必要があるかも
607
608         Query query = new Query(searchWord);
609         //取得するツイート最大数
610         query.setRpp(this.MAX_TWEET_NUM);
611         //取得するページ番号
612         query.setPage(1);
613         //追加: sinceIDを登録
614         query.setSinceId(sinceID);
615         //検索結果
616         QueryResult queryResult = null;
617         try {
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();
623         }
624
625         List<Status> tweetList = new LinkedList<Status>();
626
627         if( queryResult != null ) {
628             for(Tweet tweet: queryResult.getTweets() ) {
629                 //取得できる最大限の情報を返す
630                 SimpleUser user = new SimpleUser();
631                 //ユーザ名
632                 user.setName( tweet.getFromUser() );
633                 user.setScreenName( tweet.getFromUser() );
634                 //ユーザID
635                 user.setId( tweet.getFromUserId() );
636                 try {
637                     //ユーザイメージ
638                     user.setProfileImageURL(new URL(tweet.getProfileImageUrl()));
639                 } catch (MalformedURLException ex) {
640                     Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
641                 }
642
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);
649
650                 //情報追加
651                 tweetList.add(status);
652             }
653         }
654         //リスト逆転 一番あたらしいtweetを一番下に
655         Collections.reverse(tweetList);
656         
657         return tweetList;
658     }
659
660     /**
661      * 指定したワードを含むtweetを返す
662      * @param num 指定した数だけtweetを取得
663      * @param searchWord 検索したい単語
664      * @return
665      */
666     public List<Status> getSearchResult(int num, String searchWord) {
667         Query query = new Query(searchWord);
668         //取得するツイート最大数
669         query.setRpp(num);
670         //取得するページ番号
671         query.setPage(1);
672         //検索結果
673         QueryResult queryResult = null;
674         try {
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();
680         }
681
682         List<Status> tweetList = new LinkedList<Status>();
683
684         if( queryResult != null ) {
685             for(Tweet tweet: queryResult.getTweets() ) {
686                 //取得できる最大限の情報を返す
687                 SimpleUser user = new SimpleUser();
688                 //ユーザ名
689                 user.setName( tweet.getFromUser() );
690                 user.setScreenName( tweet.getFromUser() );
691                 //ユーザID
692                 user.setId( tweet.getFromUserId() );
693                 try {
694                     //ユーザイメージ
695                     user.setProfileImageURL(new URL(tweet.getProfileImageUrl()));
696                 } catch (MalformedURLException ex) {
697                     Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
698                 }
699
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);
706
707                 //情報追加
708                 tweetList.add(status);
709             }
710         }
711
712         //リスト逆転 一番あたらしいtweetを一番下に
713         Collections.reverse(tweetList);
714
715         return tweetList;
716     }
717
718     /**
719      * 指定したユーザのお気に入りを取得
720      * @param screenName nullの場合,自分自身のお気に入りを取得
721      */
722     public List<Status> getFavoritesTweet(String screenName) throws TwitterException {
723         // getFriendsTimelineではRetweetは表示されないので注意
724         List<Status> statuses = null;
725         if( screenName == null ) {
726             //自分自身のお気に入り取得
727             statuses = twitter.getFavorites();
728         }else {
729             statuses = twitter.getFavorites(screenName);
730         }
731         //リスト逆転 一番あたらしいtweetを一番下に
732         Collections.reverse(statuses);
733         return statuses;
734     }
735
736     /**
737      * 指定したユーザの発言を取得
738      * @param num
739      * @param userID
740      * @return
741      * @throws TwitterException
742      */
743     public List<Status> getUserTimeline(int num, int userID) throws TwitterException {
744         List<Status> statuses = twitter.getUserTimeline(userID, new Paging(1, num));
745
746         //tweet逆転
747         if (statuses != null && statuses.size() > 0) {
748             Collections.reverse(statuses);
749         }
750         
751         return statuses;
752     }
753
754     /**
755      * 指定したユーザが保持しているリスト一覧を取得
756      * @param userScreenName
757      * @return
758      */
759     public List<UserList> getUserLists(String userScreenName) {
760         List<UserList> userlist = new ArrayList<UserList>();
761         long cursor = -1;
762         try {
763             for (;;) {
764                 //ユーザリスト取得
765                 PagableResponseList<UserList> list = this.twitter.getUserLists(userScreenName, cursor);
766                 userlist.addAll( list );
767
768                 if( list.hasNext() ) {
769                     //次のカーソルを取得
770                     cursor = list.getNextCursor();
771                 }else {
772                     break;
773                 }
774             }
775         } catch (TwitterException ex) {
776             Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
777         }
778         return userlist;
779     }
780
781     /**
782      * 指定したユーザをフォローしているリストを返す
783      * @param userScreenName
784      * @return
785      */
786     public List<UserList> getUserListSubscriptions(String userScreenName) {
787         List<UserList> userlist = new ArrayList<UserList>();
788         long cursor = -1;
789         try {
790             for (;;) {
791                 //ユーザリスト取得
792                 PagableResponseList<UserList> list = this.twitter.getUserListSubscriptions(userScreenName, cursor);
793                 userlist.addAll( list );
794
795                 if( list.hasNext() ) {
796                     //次のカーソルを取得
797                     cursor = list.getNextCursor();
798                 }else {
799                     break;
800                 }
801             }
802         } catch (TwitterException ex) {
803             Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
804         }
805         return userlist;
806     }
807
808     /**
809      * 指定したユーザが追加されているリストを返す
810      * @param userScreenName
811      * @return
812      */
813     public List<UserList> getUserListMemberships(String userScreenName) {
814         List<UserList> userlist = new ArrayList<UserList>();
815         long cursor = -1;
816         try {
817             for (;;) {
818                 //ユーザリスト取得
819                 PagableResponseList<UserList> list = this.twitter.getUserListMemberships(userScreenName, cursor);
820                 userlist.addAll( list );
821
822                 if( list.hasNext() ) {
823                     //次のカーソルを取得
824                     cursor = list.getNextCursor();
825                 }else {
826                     break;
827                 }
828             }
829         } catch (TwitterException ex) {
830             Logger.getLogger(TweetManager.class.getName()).log(Level.SEVERE, null, ex);
831         }
832         return userlist;
833     }
834
835     /**
836      * 指定したリストのツイートを取得
837      * @param userScreenName ユーザ名
838      * @param listID リストID
839      * @param num 取得ツイート数
840      * @return
841      * @throws TwitterException
842      */
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));
847         //tweet逆転
848         if( tweetList != null && tweetList.size() > 0 ) {
849             Collections.reverse(tweetList);
850         }
851         return tweetList;
852     }
853
854     /**
855      * 指定したリストの最新情報を取得
856      * @param userScreenName ユーザ名
857      * @param listID リストID
858      * @param sinceID
859      * @return
860      * @throws TwitterException
861      */
862     public List<Status> getNewUserListStatuses(String userScreenName, int listID, long sinceID)
863             throws TwitterException {
864         if( sinceID == 0 ) {
865             return getUserListStatuses(userScreenName, listID, MAX_TWEET_NUM);
866         }
867         List<Status> tweetList = this.twitter.getUserListStatuses(
868                 userScreenName, listID, new Paging(sinceID) );
869         //tweet逆転
870         if( tweetList != null && tweetList.size() > 0 ) {
871             Collections.reverse(tweetList);
872         }
873         return tweetList;
874     }
875
876     /**
877      * 指定したユーザの最新の発言を取得
878      * @param userID
879      * @param sinceID
880      * @return
881      * @throws TwitterException
882      */
883     public List<Status> getNewUserTimeline(int userID, long sinceID) throws TwitterException {
884         // 一度もデータを取得していないとき
885         if (sinceID == 0) {
886             return getUserTimeline(MAX_TWEET_NUM, userID);
887         }
888
889         List<Status> statuses = twitter.getUserTimeline(userID, new Paging(sinceID));
890
891         //tweet逆転
892         if (statuses != null && statuses.size() > 0) {
893             Collections.reverse(statuses);
894         }
895
896         return statuses;
897     }
898
899     /**
900      * Twitterへログイン
901      */
902     public void loginTwitter() throws FileNotFoundException, IOException {
903         twitter = new TwitterFactory().getInstance();
904         //アカウント情報を読み込む
905         loadAccountProperties();
906         // ConsumerKeyなどを設定
907         twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
908         // ここにユーザのアクセストークンを入れる
909         AccessToken ac = new AccessToken(accessToken, secretToken);
910         twitter.setOAuthAccessToken(ac);
911         // 設定ファイルを読み込む
912         try {
913             loadProperties();
914         } catch (FileNotFoundException e) {
915             e.printStackTrace();
916         } catch (IOException e) {
917             e.printStackTrace();
918         }
919     }
920
921     /**
922      * Configurationを生成する
923      *
924      * @return
925      */
926     private Configuration getTwitterConfiguration() {
927         ConfigurationBuilder confbuilder = new ConfigurationBuilder();
928         confbuilder.setOAuthConsumerKey(CONSUMER_KEY);
929         confbuilder.setOAuthConsumerSecret(CONSUMER_SECRET);
930         return confbuilder.build();
931     }
932
933
934     /**
935      * 初回時アクセストークンを取得する際に利用する
936      * @param username
937      * @param password
938      * @throws TwitterException
939      */
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);
944         //access token取得
945         AccessToken oAuthAccessToken = twitter.getOAuthAccessToken();
946         this.accessToken = oAuthAccessToken.getToken();
947         this.secretToken = oAuthAccessToken.getTokenSecret();
948         
949         try {
950             //取得したOAuthのトークンを保存
951             saveAccountProperties();
952         } catch (IOException ex) {
953             ex.printStackTrace();
954         }
955     }
956
957     /**
958      * メッセージをつぶやく
959      *
960      * @param message
961      */
962     public void tweet(String message) {
963         twitter4j.Status status;
964         try {
965             status = twitter.updateStatus(message);
966         } catch (TwitterException e) {
967             // TODO: エラー処理
968             e.printStackTrace();
969         }
970     }
971
972     /**
973      * 返信メッセージをつぶやく
974      * @param message
975      * @param replyToStatusID
976      */
977     public void replyTweet(String message, long replyToStatusID) {
978         twitter4j.Status status;
979         try {
980             status = twitter.updateStatus(message, replyToStatusID);
981         } catch (TwitterException e) {
982             // TODO: エラー処理
983             e.printStackTrace();
984         }
985     }
986
987     /**
988      * ダイレクトメッセージを送信
989      *
990      * @param screenName
991      * @param text
992      * @throws TwitterException
993      */
994     public void sendDirectMessage(String screenName, String text)
995             throws TwitterException {
996         twitter.sendDirectMessage(screenName, text);
997     }
998
999     /**
1000      * 指定したステータスIDの発言をRetweet
1001      *
1002      * @param statusID
1003      * @throws TwitterException
1004      */
1005     public void retweet(long statusID) throws TwitterException {
1006         twitter.retweetStatus(statusID);
1007     }
1008
1009     /**
1010      * 指定した発言をお気に入りに追加
1011      * @param statusID
1012      * @throws TwitterException
1013      */
1014     public void createFavorite(long statusID) throws TwitterException {
1015         twitter.createFavorite(statusID);
1016     }
1017
1018     /**
1019      * 指定した発言のお気に入りを取り下げる
1020      * @param statusID
1021      */
1022     public void destroyFavorite(long statusID) throws TwitterException {
1023         twitter.destroyFavorite(statusID);
1024     }
1025
1026     /**
1027      * API制限数を取得
1028      *
1029      * @return
1030      * @throws TwitterException
1031      */
1032     public RateLimitStatus getRateLimitStatus() throws TwitterException {
1033         return twitter.getRateLimitStatus();
1034     }
1035
1036     /**
1037      * 自分自身のスクリーン名を返す
1038      * @return
1039      */
1040     public String getScreenName() {
1041         try {
1042             if (twitter != null) {
1043                 return twitter.getScreenName();
1044             }
1045         }catch(TwitterException e) {
1046             
1047         }
1048         return null;
1049     }
1050 }