自分がふぁぼったツイートをRSSフィードにしたいと思って、JavaでふぁぼツイートをRSSフィードにするコードを書いてみた。
環境
- Java 1.6
- ROME 1.0 (rome-1.0.jar, jdom.jar)
- Twitter4J 3.0.3 (twitter4j-core-3.0.3.jar)
サンプル ソースコード
import java.util.*;
import java.io.*;
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.conf.*;
public class TwitterFavoritesFeedMaker {
public static void main(String[] args) throws Exception {
// parameters
String outputFilePath;
if(args.length > 0){
outputFilePath = args[0];
}else{
outputFilePath = System.getProperty("user.home") + "/twitter_favorites.xml";
}
String screenname = "<YOUR SCREENNAME>";
String consumerKey = "<YOUR CONSUMER KEY>";
String consumerSecret = "<YOUR CONSUMER SECRET>";
String accessToken = "<YOUR ACCESS TOKEN>";
String accessTokenSecret = "<YOUR ACCESS TOKEN SECRET>";
TwitterFavoritesFeedMaker feedmaker = new TwitterFavoritesFeedMaker(screenname, consumerKey, consumerSecret, accessToken, accessTokenSecret);
//Writer out = new OutputStreamWriter(System.out, "Shift_JIS");
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(outputFilePath), "UTF-8");
feedmaker.output(out, "rss_2.0");
out.close();
}
private final String screenname;
private final String consumerKey;
private final String consumerSecret;
private final String accessToken;
private final String accessTokenSecret;
public TwitterFavoritesFeedMaker(String screenname, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret){
this.screenname = screenname;
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
this.accessToken = accessToken;
this.accessTokenSecret = accessTokenSecret;
}
private Twitter getTwitter(){
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey(consumerKey)
.setOAuthConsumerSecret(consumerSecret)
.setOAuthAccessToken(accessToken)
.setOAuthAccessTokenSecret(accessTokenSecret);
TwitterFactory factory = new TwitterFactory(cb.build());
AccessToken token = new AccessToken(accessToken, accessTokenSecret);
Twitter twitter = factory.getInstance(token);
return twitter;
}
private void output(Writer out, String feedType) throws Exception {
// APIからツイートを取得
final int limitCallApi = 3;
final int limitTweets = 200;
ArrayList<MiniBlogEntry> tweets = getFavoriteTweets(limitCallApi, limitTweets);
// ツイートを出力
writeEntryFeed(tweets, out, feedType);
}
/**
* ふぁぼツイートを取得する。
* @param limitCallApi 最大APIコール回数
* @param limitTweets 最大ツイート取得数(超えるけど)
* @return
* @throws Exception
*/
private ArrayList<MiniBlogEntry> getFavoriteTweets(int limitCallApi, int limitTweets) throws Exception {
ArrayList<MiniBlogEntry> tweets = new ArrayList<MiniBlogEntry>();
Twitter twitter = getTwitter();
Paging paging = new Paging(1, 200); // count=200
// APIにてツイートを取得
for(int j=0; j<limitCallApi; j++){
ResponseList<Status> statusList = twitter.getFavorites(screenname, paging);
if(statusList.size() == 0){
break;
}
for(int i=0; i<statusList.size(); i++){
Status s = statusList.get(i);
if(!s.getUser().isProtected()){ // 鍵付きユーザのツイートは含めない
MiniBlogEntry entry = new MiniBlogEntry();
entry.id = s.getId();
entry.posttime = s.getCreatedAt();
entry.screenname = s.getUser().getScreenName();
entry.body = s.getText();
tweets.add(entry);
}
}
long max_id = statusList.get(statusList.size() - 1).getId() - 1;
paging.setMaxId(max_id);
// APIを何回コールしたかのインジケーター。
System.out.print("A");
if(tweets.size() >= limitTweets){ // 指定数以上のツイートを取得していたら終了
break;
}
// for sleep
try{Thread.sleep(1000);}catch(Exception e){}
}
// APIを何回コールしたかのインジケーターを改行。
System.out.println("");
return tweets;
}
/**
* フィードを生成する。
* @param writer 出力先
* @param feedType フィードのフォーマット。rss_2.0とか。
* @throws Exception
*/
public void writeEntryFeed(ArrayList<MiniBlogEntry> tweets, Writer writer, String feedType) throws Exception{
// フィードを生成
//String feedType = "rss_2.0";
SyndFeed outfeed = new SyndFeedImpl();
outfeed.setFeedType(feedType);
outfeed.setTitle("Favorite Tweets by NI-Lab.");
outfeed.setDescription("Favorite Tweets by NI-Lab. ");
outfeed.setLink("http://www.nilab.info/");
outfeed.setAuthor("NI-Lab.");
outfeed.setLanguage("ja");
outfeed.setEncoding("UTF-8");
outfeed.setPublishedDate(new Date());
ArrayList<SyndEntry> entries = new ArrayList<SyndEntry>();
outfeed.setEntries(entries);
// エントリを生成
for(int j=0; j<tweets.size(); j++){
MiniBlogEntry tweet = tweets.get(j);
// エントリを生成
SyndEntry entry = new SyndEntryImpl();
entry.setAuthor("NI-Lab.");
entry.setTitle(deleteMeta(tweet.screenname + ": " + tweet.body));
entry.setPublishedDate(tweet.posttime);
entry.setLink("https://twitter.com/" + tweet.screenname + "/status/" + tweet.id);
// コンテンツを生成
SyndContent content = new SyndContentImpl();
content.setMode("escaped");
content.setType("text/html");
content.setValue(getDisplayableBody(tweet.screenname + ": " + tweet.body));
// コンテンツをエントリに追加
ArrayList<SyndContent> contents = new ArrayList<SyndContent>();
contents.add(content);
entry.setContents(contents);
// エントリリストに追加
entries.add(entry);
}
SyndFeedOutput output = new SyndFeedOutput();
output.output(outfeed, writer);
}
/**
* 文字列からメタ文字を削除します。
* @exception NullPointerException
*/
public static final String deleteMeta(String str) {
if (str == null){
throw new NullPointerException("deleteMeta");
}
if (str.equals("")){
return str;
}
StringBuffer result = new StringBuffer(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!isMeta(ch)) {
result.append(ch);
}
}
return result.toString();
}
/**
* メタ文字であれば true を返します。
*/
public static final boolean isMeta(char ch) {
// 0x00〜0x1f 制御文字
// 0x20 空白
// 0x21〜0x7e 図形文字
// 0x7f 制御文字
if (ch < 0x20 || ch == 0x7f){
return true;
}else{
return false;
}
}
public static String getDisplayableBody(String s){
s = sanitize(s);
s = s.replaceAll("\r\n", "\n");
s = s.replaceAll("\n", "<br />");
return s;
}
public static String sanitize(String s){
if(s == null){
return null;
}
return s.replace("&", "&").replace("<", "<").replace(">", ">").replace("'", "'").replace("\"", """);
}
public static class MiniBlogEntry {
public long id; // ツイートの固有ID
public Date posttime; // YYYY-MM-DD HH:MM:SS
public String screenname; // ユーザー名
public String body; // ツイートの中身
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("MiniBlogEntry: ");
sb.append("id=[");
sb.append(id);
sb.append("], ");
sb.append("posttime=[");
sb.append(posttime);
sb.append("], ");
sb.append("screenname=[");
sb.append(screenname);
sb.append("], ");
sb.append("body=[");
sb.append(body);
sb.append("]");
return sb.toString();
}
}
}
setPublishedDate でツイート日時を指定したのは失敗かも。本来ならふぁぼった日時を指定したいところ。見た感じ Twitter4J にふぁぼった日時を取得する機能は無さそう、そもそも Twitter API にも無さそう。。。
tags: java twiter twitter4j rome
Posted by NI-Lab. (@nilab)