Noël Café : Blog
Noëlの公開備忘録とひとりごと。コメント・トラックバックご自由に

Google Apps ScriptでTwitterに画像投稿 複数画像も! Ver.2024 (備忘録)

前々回, 前回と同じくTwitterの返信も以前(2020年)のスクリプトではできませんので修正します。
画像アップロードはAPI1.1, 文字部分の投稿はAPI2.0です(小難しい)。

画像を投稿します。複数画像も。5枚以上はスレッドにして対応します。

Step一覧

Google Apps ScriptでTwitterに投稿する方法を4回に分けて掲載しています。

  1. Twitter API登録方法 (備忘録) ← これはそのまま。
  2. Twitter APIとGoogle Apps Script 連携でツイート Ver.2024 (備忘録)
  3. Google Apps ScriptでTwitterにスレッド(返信)投稿 Ver.2024 (備忘録)
  4. Google Apps ScriptでTwitterに画像投稿 複数画像も!Ver.2024 (備忘録) ← 今ココ

POINT

今回のポイントです。

  • 画像アップロードはAPI1.1を使用, 文字の投稿はAPI2.0を使用 ← 前回と違う
  • 認証に使用するライブラリをTwitterWebService.gs → OAuth1, OAuth2に変更
  • API1.1ではClient IDは使わない、使うのはAPI Key
  • 画像は事前にmedia-updateでアップロード
  • media_id取得時はmedia_id_stringを使用
  • 返信は投稿時payloadにmedia_idで画像(メディア)を指定
  • 複数画像はmedia_idをカンマでつなげて文字列にしてから投稿

手順

前々回, 前回の作業をしている想定で書いています。

[手順1] ライブラリOAuth1の導入

ライブラリOAuth1の導入
Google Apps Scriptの画面 →「リソース」→「ライブラリ」
ライブラリのプロジェクトキー↓を入力し「追加」

1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s

バージョンは最新、Dev.Modeは無効でOK

googleworkspace / apps-script-oauth1 at GitHub

[手順2] 連携認証のスクリプトを入力

連携認証のスクリプトを入力
とりあえず何も考えずに入力(笑)。
Client IDとClient Secretは次項以降で確認する。

// 設定
const twi_api_key = ‘XXXXX’;
const twi_api_secret_key = ‘XXXXX’;

// Twitter(X) OAuth1認証
function getTwitterService1_() {
  return OAuth1.createService(‘twitter’)
    .setAccessTokenUrl(‘https://api.twitter.com/oauth/access_token’)
    .setRequestTokenUrl(‘https://api.twitter.com/oauth/request_token’)
    .setAuthorizationUrl(‘https://api.twitter.com/oauth/authorize’)
    .setConsumerKey(twi_api_key)
    .setConsumerSecret(twi_api_secret_key)
    .setCallbackFunction(‘twiAuth1Callback_’)  // コールバック関数名
    .setPropertyStore(PropertiesService.getUserProperties());
}
 
// OAuth1コールバック
function twiAuth1Callback_(request) {
  var twitterService = getTwitterService1_();
  var isAuthorized = twitterService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput(‘Success! You can close this tab.’);
  } else {
    return HtmlService.createHtmlOutput(‘Denied. You can close this tab.’);
  }
}

// OAuth1リセット
function resetTwiOAuth1() {
  getTwitterService1_().reset();
}
 
// OAuth1認証用URL取得
function getTwiOAuth1URL() {
  Logger.log(getTwitterService1_().authorize());
}

ちなみにOAuth2を使用することになるのでOAuth1と明示した。

ここで使用するのはClienet IDでなくAPI Key。
(コード見本はClient IDって書いてあるものあり。)

[手順3] Twitter API Key and Secretを入手

Twitter API keyとAPI secret keyを確認し上のコードのxxxxxxxx部分に入力する。
Twitter Developer Portal → Projects & Apps から該当Appを開く
「API Key and Secret」にある。
必要に応じて再作成する。
ついでに他のところも問題なさそうか確認する。

[手順4] Google Apps ScriptでTwitterアプリの認証作業

  1. getTwiOAuth1URL関数実行
    Google Apps Scriptの画面 →「関数の選択」で「getTwiOAuth1URL」を選択し実行▶︎
  2. ログから認証用URLを取得
    Google Apps Scriptの画面 →「表示」→「ログ」
    https://api.twitter.comから始まるURL
  3. 認証用URL(上で取得)をブラウザで開く
    認証画面が出るので内容を確認(できること/できないこと)し認証
    成功するとSuccessと表示される。
    閉じてOK。

[手順5] Twitterに投稿

前回作成した返信機能付きpost_tweet関数を使用します。
ライブラリOAuth2も引き続き使います。
引数をmsg(投稿する文章), re_id(返信元のツイートID), img_urls(画像のURL配列)、
戻り値を今回投稿したツイートIDとします。

エンドポイントは今回から事前に変数に設定しています。

// twitterエンドポイントURL
const twi_endpoint1 = “https://upload.twitter.com/1.1/media/upload.json”;
const twi_endpoint2 = “https://api.twitter.com/2/tweets”;

// twitterへ投稿
// 返り値はツイートした投稿のID
function post_tweet(msg, re_id, img_urls){
  var service1 = getTwitterService1_();
  var service2 = getTwitterService2_();
  if (service1.hasAccess() && service2.hasAccess()) {

    var img_ids = [];
    if(!img_urls){
      // 画像がない時はスキップ
    }else if(img_urls.length > 4){
      // 5枚以上ある時は分割して投稿。最初の投稿の返信(スレッド)になる。文章は同じ。*1
      var img_urls_now = img_urls.splice(0,4);
      var tw_id = post_tweet(msg, re_id, img_urls_now);
      tw_id = post_tweet(msg, tw_id, img_urls);
      return tw_id;
    }else if(img_urls){
      // 画像が4枚以下の場合は順番にエンコード→アップロードする。*2
      // idを取得して配列imgidsに返す。
      for(var i = 0; i < img_urls.length; i++){
        var img_blob = UrlFetchApp.fetch(img_urls[i]).getBlob();
        var img_64 = Utilities.base64Encode(img_blob.getBytes());
        var img_upload = service1.fetch(
          twi_endpoint1, { 
            'method' : "POST", 
            'payload': { 'media_data': img_64 } 
          }
        ); 
        var result1 = JSON.parse(img_upload.getContentText());
        // media_idをimg_idsに格納。
        img_ids[i] = result1.media_id_string;
      }
    }

    // 条件に合わせてpayload作成 *3
    var payload = "";
    if (re_id && img_ids.length > 0){
      // 返信, 画像あり
      payload = {
        text: msg, 
        reply: {in_reply_to_tweet_id: re_id},
        media: {media_ids: img_ids}
        };
    } else if (re_id) {
      // 返信, 画像なし
      payload = {
        text: msg, 
        reply: {in_reply_to_tweet_id: re_id}
        };
    } else if (img_ids.length > 0){
      // 画像あり, 返信でない
      payload = {
        text: msg, 
        media: {media_ids: img_ids}
        };
    } else {
      // 返信でない, 画像なし
      payload = {text: msg};
    }

    // 投稿
    var response = UrlFetchApp.fetch(twi_endpoint2, {
      method: ‘POST’,
      ‘contentType’: ‘application/json’,
      headers: { Authorization: ‘Bearer ‘ + service2.getAccessToken() },
      muteHttpExceptions: true,
      payload: JSON.stringify(payload)
    });
    var result = JSON.parse(response.getContentText());
    var twi_id = result.data.id;
    return twi_id;
  } else {
    Logger.log(“Not Authorized”);
    return null;
  }
}
function test_tweet(){
  // 連続ツイートの見本
  var twi_id1 = post_tweet(“GASツイートテスト”, “”, [“url1”, “url2”]);
  var twi_id2 = post_tweet(“GASツイート返信テスト”, twi_id1);
}

*1 (2020Ver.と同じ)
5枚以上画像がある場合の対応
同じ関数(post_twitter)を呼び出すのは良くない気もするけど、
スクリプトが単純になるので。
5枚以上の場合はスレッド(返信)になります。
最後の投稿のIDが最終的に返り値になります。

*2 (2020Ver.と同じ)
画像を投稿する場合は、文章を投稿する前に、画像をアップロードします。
画像をBlobを経由してBase64に変換させ(中身については私はよくわかっていないw)
media/upload.jsonにPOST。
media_id_stringを取得。
media_idは数値として取得してしまい丸められてしまうのでダメ(数値の大きさの問題)。

*3
文章を投稿する時に、media-idsで画像IDを投稿。
画像IDは配列で渡す(API1.1と違う)。
payloadは条件分岐して作成。

長かったですが、これでtwitter投稿の関数作成はこれで終わりです。
これを使って、Blog投稿お知らせやInstagramを自動投稿していきたいと思います。

Reference

余談

とりあえず、1年くらい動かなかったTwitter自動投稿が直りました(笑)。
重い腰を持ち上げるのに時間はかかるし、
やり始めると一日作業だし。
(私、ノンプログラマーです。)

それにしても2つのAPIを使うのは煩雑で面倒ですね。

Leave a Reply

*


CAPTCHA



Trackback URL