Twitter を使って何か有益情報を発信したい、と常々思っていました。そこで思いついたのが、フランス語の難関単語(動詞)を呟くこと。
仏検1級レベルの単語帳は本屋に行ってもなかなか見つからないので、筆者が今までの仏語学習の中で出会ってきた難関単語を個人的に蓄積してきました。
せっかくならば Twitter で定期的に仏単語を放出していくと誰かに有益になるのでは!?、と思ったのです
この記事では、GoogleSpreadSheet で纏めたデータを、GASを使って Twitter に自動投稿するスクリプトを作成した際に個人的に躓いたポイントと実際のスクリプト を紹介します。
GoogleSpreadSheetのデータをGASを使ってTwitterに自動投稿
早速手順ですが、GoogleSpreadSheetのデータを上から順番に1行ずつ抽出し、Twitterに自動投稿するだけです。
- GoogleSpreadSheetに投稿するデータを作成する
- Google Apps Script(GAS)を使って 「上記データを機械的(自動的)に抽出した上で、Twitter に自動投稿する」 という仕組み(プログラム)を作る。JavaScript というプログラミング言語で作ります
- GASがTwitterにアクセスできるように(自動投稿できるように)、Twitter APIキー(Consumer Key)を取得する
詳しい作成方法・手順は以下サイトにすべて載っています!非常に参考になりました。
自分専用のTwitterBotを作り方を完全公開します【コピペOK】
個人的に躓いたポイント
エラー(1):{“errors”:[{“message”:”Could not authenticate you”,”code”:32}]}
Twitter 認証も終えて、いざ「postUpdateStatus」関数を実行して、実際にTwitterに自動投稿する際に以下エラーが発生。これを解決するのは相当に悩みました。
https://api.twitter.com のリクエストに失敗しました(エラー: 401)。サーバー応答の一部: {“errors”:[{“message”:”Could not authenticate you”,”code”:32}]}(応答の全文を見るには muteHttpExceptions オプションを使用してください)(行 443、ファイル「Service」、プロジェクト「OAuth1」)
いくらググっても解決方法がわからなかったのですが、先ほどのリンクサイトの中にあったコメントが参考になりました!
- (前提)TwitterのAPI Key(Consumer Key)は正しいものがGASに記載されている
- Twitter DevelopersのページでAppの設定を “Read and write” に変更する
- その後に一度 GAS で「reset」関数を実行(Run)してTwitter認証を解除のうえ、改めて「authorize」関数を実行して認証を通す
- 「authorize」関数を実行後、『表示』>『ログ』で表示されたURLで認証する
- いざ、もう一度「postUpdateStatus」関数を実行してみると問題なく投稿できました!
エラー(2):{“errors”:[{“code”:187,”message”:”Status is a duplicate.”}]}
自動投稿が問題なく出来ているかを確認するために、以下のテスト関数を実行すると以下エラーが表示されてしまいました。
<テスト関数>
// 投稿テスト用
function TweetTest() {
var service = twitter.getService();
var endPointUrl = ‘https://api.twitter.com/1.1/statuses/update.json’;
var response = service.fetch(endPointUrl, {
method: ‘post’,
payload: {
status: ‘Tweet Test’
}
});
}
ちなみにエラー内容は以下の通り。
Exception: https://api.twitter.com のリクエストに失敗しました(エラー: 403)。サーバー応答の一部: {“errors”:[{“code”:187,”message”:”Status is a duplicate.”}]}(応答の全文を見るには muteHttpExceptions オプションを使用してください)
これに対しては以下をご参考ください!
- (問題点)連続で同じツイートすると出るエラー。Twitterは同じ内容をを連続して投稿できない。
- (対応1)テストツイート内容を変更(”Test Tweet” → “Test Tweet 2” 等)
- (対応2)Twitterアプリ上でテストツイートを削除
- いざ、もう一度「TweetTest」関数を実行してみると問題なくテストツイート投稿できました!
実際のスクリプト
ツイートするデータは GoogleSpreadSheet で以下のように準備。
<こちらが GAS>
// 認証用インスタンス
var twitter = TwitterWebService.getInstance(
'XXXXXXXXXXXXX', // 作成したアプリケーションの Twitter API key
'XXXXXXXXXXXXX' // 作成したアプリケーションの Twitter secret key
);
// アプリを連携認証
function authorize() {
twitter.authorize();
}
// 認証解除
function reset() {
twitter.reset();
}
// 認証後のコールバック
function authCallback(request) {
return twitter.authCallback(request);
}
// 投稿テスト用
function TweetTest() {
var service = twitter.getService();
var endPointUrl = 'https://api.twitter.com/1.1/statuses/update.json';
var response = service.fetch(endPointUrl, {
method: 'post',
payload: {
status: 'Test Post'
}
});
}
// セルを取得
var sheetData = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet-Name"); // ""内はシート名
var postMessageCell = sheetData.getRange(2, 2); // セルの位置=B2
// ツイートを日次投稿
function postUpdateStatusDailyEn() {
for (var i = 0; i < 5; i++ ) {
var message = pickUpTweetDaily();
if (message == "") {
return;
}
var service = twitter.getService();
var response = service.fetch('https://api.twitter.com/1.1/statuses/update.json', {
method: 'post',
payload: { status: message }
});
}
}
// ツイートを週次投稿
function postUpdateStatusWeeklyEn() {
for (var i = 0; i < 25; i++ ) {
var message = pickUpTweetWeekly();
if (message == "") {
return;
}
var service = twitter.getService();
var response = service.fetch('https://api.twitter.com/1.1/statuses/update.json', {
method: 'post',
payload: { status: message }
});
}
}
// 日次投稿
/**
* ツイートを上から順に選択していく
* 処理の中で前回の番号を保持していくことは出来ないので
* 投稿された回数をシートに保存しておき、一番投稿された回数が少ない記事を次の記事にする
**/
function pickUpTweetDaily() {
var titleRow = 1; // 『投稿内容』と書いている部分は1行目
var startRow = 1 + titleRow; // 1行目は『投稿内容』と書いているので2行目から
var startCol = 1;
var endRow = sheetData.getLastRow() - titleRow; // 最後の行まで(2行目から始まっているので-1している)
var endCol = 2; // 『日次ツイート回数』の列までなので2列目まで
// 投稿を一括で取得する
var cells = sheetData.getRange(startRow, startCol, endRow, endCol).getValues();
// ちなみにcellsの中身は
// [ [ '投稿内容', '日次ツイート回数'] , [ '投稿内容', '日次ツイート回数'] , [ '投稿内容', '日次ツイート回数'] ,....,]
// という形式になっている
var postData = cells[0]; // postData = [ '投稿内容', '日次ツイート回数'] なので postData[0] => 投稿内容, postData[1] => 日次ツイート回数
var row = 1 // 行番号(選ばれたらその行の投稿された回数を+1するために持っておく)
for (var i = 0, il = cells.length; i < il; i++ ) {
// 日次ツイート回数が少なかったら更新(回数が同じであればそのまま)
if (cells[i][1] < postData[1]) {
postData = cells[i]
row = 1 + i // 行は1から始まるので+1して保存しておく
}
}
var postMessage = postData[0];
// 投稿する内容の日次ツイート回数の部分のセルだけ取得して、+1して更新する
var updateCell = sheetData.getRange(row + titleRow, 2, 1, 1);
updateCell.setValue(postData[1]+1);
return postMessage;
}
// 月次投稿
/**
* ツイートを上から順に選択していく
* 処理の中で前回の番号を保持していくことは出来ないので
* 投稿された回数をシートに保存しておき、一番投稿された回数が少ない記事を次の記事にする
**/
function pickUpTweetWeekly() {
var titleRow = 1; // 『投稿内容』と書いている部分は1行目
var startRow = 1 + titleRow; // 1行目は『投稿内容』と書いているので2行目から
var startCol = 1;
var endRow = sheetData.getLastRow() - titleRow; // 最後の行まで(2行目から始まっているので-1している)
var endCol = 3; // 『週次ツイート回数』の列までなので3列目まで
// 投稿を一括で取得する
var cells = sheetData.getRange(startRow, startCol, endRow, endCol).getValues();
// ちなみにcellsの中身は
// [ [ '投稿内容', '日次ツイート回数', '週次ツイート回数'] , [ '投稿内容', '日次ツイート回数', '週次ツイート回数'] , [ '投稿内容', '日次ツイート回数', '週次ツイート回数'] ,....,]
// という形式になっている
var postData = cells[0]; // postData = [ '投稿内容', '日次ツイート回数', '週次ツイート回数'] なので postData[0] => 投稿内容, postData[1] => 日次ツイート回数 , postData[2] => 週次ツイート回数
var row = 1 // 行番号(選ばれたらその行の投稿された回数を+1するために持っておく)
for (var i = 0, il = cells.length; i < il; i++ ) {
// 週次ツイート回数が少なかったら更新(回数が同じであればそのまま)
if (cells[i][2] < postData[2]) {
postData = cells[i]
row = 1 + i // 行は1から始まるので+1して保存しておく
}
}
var postMessage = postData[0];
// 投稿する内容の週次投稿回数の部分のセルだけ取得して、+1して更新する
var updateCell = sheetData.getRange(row + titleRow, 3, 1, 1);
updateCell.setValue(postData[2]+1);
return postMessage;
}
以上参考となれば幸いです!
コメント