導入
0. bot垢を作り、https://dev.twitter.com/ で application を作成
このとき、settingタブ の Application type の Access を 「Read, Write and Access direct messages」 にしておく。 DetailsタブのYour access tokeで設定が変わったか確認する。Recreateしたほうがいいのかもしれない。 OAuth Toolタブの4つの文字とか数字の羅列は後で使うのでメモっとく
1. Node.jsをインストールします
2. コマンドプロンプトとかで
...> node -v
v0.10.18
...> npm -v
1.3.8
以上のようになればインストール成功です
(versionは自分がbot作ったときのなので最新版じゃないかも)
3. matchaフォルダにapp.jsを作ります
4. コマンドプロンプトでmatchaフォルダに移動します
5. npmでtwitterモジュールを導入します。今回はnode-twitterを使いました
.../matcha> npm install twitter
6. ツイートをするプログラムを書いてみる
app.js
var twitter = require('twitter');
var print = require('util').log;
var bot = new twitter({
consumer_key : /* 各自記入 */,
consumer_secret : /* 各自記入 */,
access_token_key : /* 各自記入 */,
access_token_secret : /* 各自記入 */
});
bot.updateStatus("ぽよ",function(data){
if(data.data){
/* エラーが発生したとき */
var err = JSON.parse(data.data);
var str = err.errors[0].code + " - " + err.errors[0].message;
print("[error] " + str);
}
});
consumer_keyとかは前述のアレ
7. 起動します
.../matcha> node app.js
Twitter APIについて
手動更新しなくてもTLが流れていくやつとかはStreaming APIを利用している。
Streaming APIを使うとリアルタイムでいろいろ情報が流れてくる。
詳しくは公式
Node.jsについて
非同期処理という特徴がある。
重い処理をする際、結果を待たずに次の処理を始める。結果の受け取りをコールバック関数が行う。
詳しくはgoogle先生に
User Stream を使う
var twitter = require('twitter');
var print = reuire('util').log;
var ins = require('util').inspect; // Object型を表示するときに使う
var bot = new twitter({
consumer_key : /* 各自記入 */,
consumer_secret : /* 各自記入 */,
access_token_key : /* 各自記入 */,
access_token_secret : /* 各自記入 */
});
// User Stream
bot.stream('user', function(stream){
stream.on('data',function(data){
// データを受信した時に実行される
// ツイート以外のもの(ツイ消しとかフォロー情報とかも流れてくる)
// 接続開始時にFF情報が入ってくる仕様らしい
if('friends' in data){
print("接続しました");
return;
}
if(!('text' in data)){return;} // ツイート以外はさよなら
print(ins(data)) // 表示
/* ここにbotとしての処理を書く */
});
});
dataの中にはいろんな情報が流れてくる
dataはJSON形式
dataオブジェクトのなかにtextというプロパティが含まれていれば、ツイートだと判断する
フォローしているユーザーのツイートが流れてくる
- 使いそうなやつ
BOT_IDに自分のIDを入れとく。IDはwhotwiとかで調べられる。Janetterだとプロフィールから見られる。10桁ぐらいの数字列。stream.on('data',function(data){ ... var screen_name = data.user.screen_name; // @aaaaaaa var user_name = data.user.name; // 垢名 var user_id = data.user.id_str; // ID(文字列) var status_id = data.id_str; // ツイートID(文字列) var twtext = data.text; // ツイート内容 var reply_user_id = data.in_reply_to_user_id_str; // リプ元のツイート var reply_status_id = data.in_reply_to_status_id_str; // リプ先のユーザーID(文字列) var twdate = new Date(data.created_at); // ツイート日時 var via = data.source.replace(new RegExp(/<[^>]+>/g),''); // via var isMention = data.entities.user_mentions.length ? data.entities.user_mentions[0].id_str == BOT_ID : false; // 自分へのreplyかどうか var isRetweet = data.retweeted_status ? true : false; // 公式RTかどうか var isRetweet2 = (new RegExp(/(R|Q)T @[^\s ]+/g)).test(twtext); // 非公式RT,QTかどうか var isLink = data.entities.urls.length ? true : false; // リンクを含むかどうか /* 自分自身のツイートは除外 */ if(user_id == BOT_ID){ return; } /* リンク付きとRTはさよなら */ if(isRetweet || isRetweet2 || isLink){ return; } /* 除外処理 */ twtext = twtext.replace(new RegExp(/@[^\s ]+/g),'') // @aaaaaは全て除外 .replace(new RegExp(/#[^\s ]+/g),'') // ハッシュタグを全て除外 .replace(new RegExp(/^[\s ]+/),'') // 前の空白を除外 .replace(new RegExp(/[\s ]+$/),''); // 後ろの空白を除外 ... });
screen_nameでも判定してもいいけど、変えたとき面倒。
data.entities.user_mentions[0]は先頭の@だけだから、復数リプの2番目だったときは無視する。
- 関数化しておく
status_idを入れてツイートするとin_reply_toが付く// エラー処理用 var twProcessError = function(data){ if(data.data){ var err = JSON.parse(data.data); var str = err.errors[0].code + " - " + err.errors[0].message; print("[error] " + str); } } function tweet(text, status_id){ bot.updateStatus(text, {in_reply_to_status_id : status_id}, twProcessError); } function reply(screen_name, text, status_id){ tweet('@' + screen_name + ' ' + text, status_id); }
- 実装例
stream.on('data',function(data){ ... // オウム返し if(isMention){ reply(screen_name, twtext, status_id) } ... });
// 特定ワードに飯能 if((new RegExp(/.*抹茶.*/)).test(twtext)){ tweet("抹茶おいしい!") }
- favる
node-twitterのTwitterAPI ver1.1対応がめっちゃ適当だから、これだと動かないfunction favorite(id_str){ bot.favoriteStatus(id_str, twProcessError); }
- 手直し
/node_modules/twitter/lib/twitter.js
createFavoriteのvar urlをいじる
- 手直し
Twitter.prototype.createFavorite = function(id, params, callback) {
var url = '/favorites/create.json?id=' + escape(id);
this.post(url, params, null, callback);
return this;
}
/favorites/create/:id.json はver1の仕様なので、
/favorites/create.json?id=:id のようにver1.1に対応させる
node-twitterの中身見たら、こういうの結構多いし、ver1にしか無いAPIとかある
でも自分で1から作るより楽だから文句言わず手直ししてる
やっぱ自分でモジュール書きました。ほぼコピペだけど
再接続処理
streamはいつか切れるので、再接続処理しないとアレです
割と適当に実装したら何か動くのでこれでいいんだと思います。
function bot_run(){
bot.stream({},function(stream) {
stream.on('data', function(data) {
//...
});
stream.on('error', function(error) {
print("error : " + (ins(error)));
});
stream.on('end', function() {
print("stream end.");
// 再接続
setTimeout( function(){ bot_run() }, 1000);
});
});
};
bot_run();