node.jsを使ってTwitterのbotを開発してみよう その2
前回は、Twitterモジュールを使って、いろいろなコマンドを使って、基本的な機能を実装するやり方を紹介しました。今回は、その基本的な機能に応用を加えて、より高度な機能を実装していくためのやり方を紹介していきます。
##自動的に機能を実装するようにする
前回やってきた機能についてですが、nodeコマンドで実行した時は機能しますが、それ以降は全く機能しなくなるんですよね...
Dateを取得して、13時にツイートをするようにコードを書いたとしても機能してくれません。ではどうしたら自動的に機能してくれるようになるのか。ここでめちゃくちゃ重宝するのがsetIntervalです。
const tweet = 'statuses/update';
bot.post(tweet, {status: "百合は尊い"}, function(err, tweet, res) {
console.log("\n下記の内容をツイートしました!\n\n" + tweet.text);
});
前回はこんな感じでツイートをする機能を書いていきましたね。ちなみに、コマンドは定数に代入することも出来るので、このようにして定数に代入しておくことで、「この機能をするためのコマンドなんだっけ...」といちいち考える必要がなくなるのですごくおすすめです!
この機能にsetIntervalを加えてみます。
const tweet = 'statuses/update';
setInterval(function() {
bot.post(tweet, {status: "百合は尊い"}, function(err, tweet, res) {
console.log("\n下記の内容をツイートしました!\n\n" + tweet.text);
});
}, 60_000); // 1分ごと
こんな感じです。functionの時間指定の部分は、1,000で1秒なので、
1,000 * 60 = 60,000
60,000と指定することで、1分ごとに機能することが出来ます。こうすることで、1分ごとにツイートをする機能を取得することが出来るようになります。
ただ、このままではツイート重複のエラーが出てしまうので、よくある方法としては、配列内に文字列をたくさん入れて、ランダム抽出する方法です。これはかなり使えるのですごくおすすめです!
const tweet = 'statuses/update';
let lily_texts = ["百合は尊い", "とりあえず百合は尊い", "やっぱり百合は尊い", "そして百合は尊い"];
let lily_text = lily_texts[Math.floor(Math.random() * lily_texts.length)]; // ランダム抽出
setInterval(function() {
bot.post(tweet, {status: lily_text}, function(err, tweet, res) {
console.log("\n下記の内容をツイートしました!\n\n" + tweet.text);
});
}, 60_000); // 1分ごと
まずはlily_textsにツイートしたい内容をどんどん書いていきます。そして、lily_textで、lily_textsの要素の中からランダムに抽出しています。このようにすることで、重複エラーはほぼ起こらなくなります。ただ、乱数なので、稀に被ってしまうことがあります。
さて、これで自動的にツイートしたり、リツイートしたりする方法が分かりましたが、機能を実装する際に、決まった時間にだけ行いたいときもあると思います。そんなときは、setInterval内でDateを取得すれば大丈夫です!
setInterval(function() {
const now = new Date();
const hour = now.getHours(); // 時を取得
const min = now.getMinutes(); // 分を取得
if(hour === 8 && min === 0) { // 8時になったら
bot.post(tweet, {status: lily_text}, function(err, tweet, res) {
console.log("\n下記の内容をツイートしました!\n\n" + tweet.text);
});
};
}, 60_000); // 1分ごと
このように書くと、午前8時になったときだけ、ツイートをするようになります。
setInterval(function() {
const now = new Date();
const min = now.getMinutes(); // 分を取得
if(min === 0) { // 1時間ごとに
bot.post(tweet, {status: lily_text}, function(err, tweet, res) {
console.log("\n下記の内容をツイートしました!\n\n" + tweet.text);
});
};
}, 60_000); // 1分ごと
また、こういう風に書くと、setIntervalは1分ごとに機能していますが、ツイートをするのは1時間ごとになります。いろいろ試してみましょう!
まだフォローしていないフォロワーのみフォローする
次に、botのことをフォローしてくれた方をフォローし返すための機能を書いてみましょう。
const follower_list = 'followers/list';
const bot_name = {screen_name: "maki_lily_bot"};
setInterval(function() {
bot.get(follower_list, bot_name, function(err, follower_list, res) {
console.log(follower_list);
});
}, 60_000) // 1分ごと
まずはbotのフォロワーを確認する必要があるので、botのフォロワーを取得するコマンドから書いていきましょう。情報を取得するだけなので、getメソッドですね。そして、フォロワーを確認する機能で必須なパラメータはscreen_nameです。(@から始まるid名のことを指します。)
さて、次は取得したフォロワーのことをフォローする機能を書いていきますが、フォローする機能は、通常は1回だけ行うことが出来るようになっています。では、どうすれば一度で一気にフォロワーのことをフォロー出来るようにするのか。ここで使えるのが繰り返し構文です。botのフォロワーの人数分繰り返したいので、配列を使った繰り返しを行うことが出来るfor...of文を使っていきましょう。
`javascript:bot.js
setInterval(function() {
bot.get(follower_list, bot_name, function(err, follower_list, res) {
for(let followers of follower_list.users) { // フォロワーの人数分繰り返す
console.log(followers);
};
});
}, 60_000) // 1分ごと
`
ここで注意してほしいのが、配列を指定するときに、follower_listと書くのではなく、follower_list.usersと書くということです。理由は、フォロワー一覧を取得してみると、返ってくるのが配列ではなく、ハッシュになっているからです。その結果の中身をよく見てみると、usersというキーの中に、フォロワーさん達の情報が配列形式になって格納されています。つまり、follower_listのキーであるusersを指定してあげることで、配列を指定することが出来るということです。この状態で結果を見てみると、その配列の中身が表示されます。
これでフォロワーの人数分機能を実装することが出来るようになりました。さて、次は、すでにbotがフォローしている人はフォローしないようにしなければいけません。そうしないと、「このフォロワーさんはすでにフォローしていますよ」とエラーが出てしまいます。とはいっても、やり方はそこまで難しくはありません。
`javascript:bot.js
setInterval(function() {
bot.get(follower_list, bot_name, function(err, follower_list, res) {
for(let followers of follower_list.users) { // フォロワーの人数分繰り返す
if(followers.following === true) { // すでにフォローしていたら飛ばす
continue;
}else {
console.log(followers.following);
};
};
});
}, 60_000) // 1分ごと
`
フォロワー一覧の結果をもう一度よく見てみると、【following】というキーがありますよね? これは、botがその人のことをフォローしているのかを真偽値の値で教えてくれるところなんです。trueと書かれていれば、その人のことはすでにフォローしているということです。ということは、trueの時は、その回は飛ばしてしまえばいいということですよね?繰り返し構文を飛ばすために使うコマンドはcontinueです。これですでにフォローしている人のことはフォローしないようにすることが出来ました。
ただ、後1つだけエラーが起こる可能性が残されています... それが、鍵垢です。鍵垢は、普通の垢とは違い、フォローする前にリクエストを送る必要があります。またフォローする機能を実装する前に、そのユーザーが承認してくれれば全く問題ないんですが、してくれなかった場合は、またフォローしてしまうことになるんです。最後にそれを防ぐ必要があります。ただ、それも難しくはありません。フォロワーにフォローリクエストを送ったかどうか確認するには【follow_request_sent】という部分を見ます。trueなら送っているということになります。これを利用して、
`javascript:bot.js
const follow = 'friendships/create';
setInterval(function() {
bot.get(follower_list, bot_name, function(err, follower_list, res) {
for(let followers of follower_list.users) { // フォロワーの人数分繰り返す
if(followers.following === true) { // すでにフォローしていたら飛ばす
continue;
}else {
if(followers.follow_request_sent === true) { // リクエストを送っていたら飛ばす
continue;
}else{
bot.post(follow, {user_id: followers.id_str}, function(err, follow, res) {
console.log("\n" + followers.name + "さんのことをフォローしました!");
});
};
};
};
});
}, 60_000) // 1分ごと
`
これで遂に完成です! ちなみに、getメソッドの中で、postメソッドを使うときは、そのスコープ外のgetメソッドの値も利用することが出来るので、上記みたいに、user_idを書くときに、followers.id_strとすることで、指定することが出来ます。 本当にお疲れさまでした。
まとめ
今回は基本的な機能に加えて、応用を使って、さらに高度な機能を実装するための方法を紹介しました。この方法を上手く使いこなせるようになると、フォロー機能だけでなく、いいね機能やリツイート機能などもすごく細かい設定をすることが可能になります。是非頑張ってみてください!なお、私が百合botを作成しているときに、一番苦闘した機能は返信機能です。マジでめちゃくちゃ苦労しました。多分30時間以上苦しんだかもしれません。もし要望があった場合は、返信機能のやり方も紹介してみようかなと思います。ありがとうございました。 ノシ