Google Apps Scriptで動くTwitterAPIのbotを作ってみたよ

2023/03/25追記:
アリーナの廃止によりアリーナスコアが取得できなくなりました。
アリーナ関連の取得コードを削除することでエラー回避できます。

半年ほど前から真面目に練習を始めたAPEX。
2022年になってからはランクマッチにも挑み始めて、上手い人の協力も借りつつ無事ダイヤモンド到達もできました。

APEXにはゲーム内スコアをトラッキングしてくれるトラッキングサイトが存在しています。

主に世界ランキングの順位を調べたり、ランクごとの分布・プレイヤー比率を調べるために使うサイトなんですが、各ユーザーごとのトラッキングデータを調べることもできます。

このサイトから自分のAPEXアカウントの数値を取得すればランクマッチのポイントや変遷を自動で発信できそう。
Twitterで日々ランクマの進捗をツイートしたりしているのだし、botで自動で配信できるようにしてしまおう。

 トラッカーサイトのAPI

APEXのトラッカーサイトにはまさかのAPIが存在していました。

このAPIを叩くとランクポイントの情報を取得することができます。

Twitter API

吐き出し先はTwitterなのでTwitter APIを使ってみます。
昔使ったときは申請がめんどくさいイメージあったけど、今は簡易化されたのかなんなのか即効で使うことができるようになっていました。ありがたい。

https://developer.twitter.com/en/docs/twitter-api

使っていくAPIはTwitter API v2のManage Tweetsです。
endpointにPOSTすることで新規ツイートを投稿することができます。

GASを書いていく

まずはAuth1.0の認証。
GASで認証するにはライブラリの登録が必要です。

ライブラリー登録キー
1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s

まったくうまくいかなくていろんなサイトを参考にしてみた結果、以下のコードでうまくできました。

//認証用の各種変数
const apikey = 'API Key';
const apisecret='API Secret Key';
const tokenurl = "https://api.twitter.com/oauth/access_token";
const reqtoken = "https://api.twitter.com/oauth/request_token";
const authurl = "https://api.twitter.com/oauth/authorize";
const endpoint = "https://api.twitter.com/1.1/statuses/update.json";  //ツイートをするエンドポイント
const endpoint2 = "https://api.twitter.com/2/tweets";  //v2のツイートするエンドポイント
const appname = "apex score bot";  //アプリの名称
 
//認証実行
function startoauth(){
  
  //認証済みかチェックする
  const service = checkOAuth(appname);
  if (!service.hasAccess()) {
    //認証画面を出力
    console.log('OAuth1.0認証');
  } else {
    //認証済みなので終了する
    console.log("すでに認証済みです。");
  }
}
 
//認証チェック用関数
function checkOAuth(serviceName) {
  return OAuth1.createService(serviceName)
    .setAccessTokenUrl(tokenurl)
    .setRequestTokenUrl(reqtoken)
    .setAuthorizationUrl(authurl)
    .setConsumerKey(apikey)
    .setConsumerSecret(apisecret)
    .setCallbackFunction('authCallback')
    .setPropertyStore(PropertiesService.getUserProperties());
}
 
//認証コールバック
function authCallback(request) {
  const service = checkOAuth(request.parameter.serviceName);
  const isAuthorized = service.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('認証が正常に終了しました');
  } else {
    return HtmlService.createHtmlOutput('認証がキャンセルされました');
  }
}

//アクセストークンURLを含んだHTMLを返す関数
function authpage(){
  const service = checkOAuth(appname);
  const authorizationUrl = service.authorize();
  console.log(authorizationUrl)
}

ベースはこの記事を参考にしたコード
UIとかいらないのでHTMLの部分削除したり、変数宣言をconstに変えたりしてるけどそれくらいの変更。

authpageの関数を実行して、認証用URLにアクセスしましょう。
アクセスするとTwitterの認証画面が表示されるので、認証。成功したらOKです。

次、API叩くコード


function postTweet(message) {
  const endpoint = 'https://api.twitter.com/2/tweets'
  const service = checkOAuth('apex score bot');

  const option = {
      'method' : 'POST',
      'payload' : JSON.stringify({
        text : message
      }),
      'muteHttpExceptions' : true,
      'contentType': 'application/json',
    }
  const f = service.fetch(endpoint, option);
  console.log(f.getContentText())
}

server.fetchでPOSTするとツイートを投稿できます。
実際に投稿されるとこんな感じ。ツイート元になるアプリ名は自分で設定したapex score botになってます。

スケジュールで定期実行にしておくと自分の現在のランクマッチ進捗が勝手に発信される感じにできましたとさ。一応全体像のGASコードも載せておきます。

function apexTrackerGG() {
  const endpoint = 'https://public-api.tracker.gg/v2/apex/standard/profile/psn/ban_chan_a/sessions';
  const header = {
    "TRN-Api-Key":"[APEX Tracking ggのAPI Key]","Accept":"application/json"
  }
  const ajax = UrlFetchApp.fetch(endpoint, {'method' : 'get', 'headers' :header });
  const responseData = JSON.parse(ajax.getContentText());

  const items = responseData.data.items; //取得できる全マッチ
  const today = dayjs.dayjs().format('YYYY-MM-DD');
  const targetObject = items.filter(obj => {
    const endDate = obj.metadata.endDate.value;
    const time = dayjs.dayjs(endDate).format("YYYY-MM-DD");
    return time === today;
  });

  //最終結果
  const match = targetObject[0].matches[0];
  const resultObject = {
    rank: match.stats.rankScore.metadata.rankScoreInfo.name,
    rankScore: match.stats.rankScore.value,
    rankScoreChange: 0,
    arena: match.stats.arenaRankScore.metadata.arenaRankScoreInfo.name,
    arenaRankScore: match.stats.arenaRankScore.value,
    arenaRankScoreChange: 0
  };

  //RP増減の加算
  targetObject.forEach(x => {
    const rank = x.stats.rankScoreChange.value;
    const arena = x.stats.arenaRankScoreChange.value;
    resultObject.rankScoreChange = resultObject.rankScoreChange + rank;
    resultObject.arenaRankScoreChange = resultObject.arenaRankScoreChange + arena;
  });
  const tweetText = createTweet(resultObject);
  console.log(tweetText);
  return postTweet(tweetText);
}

//Tweet本文
function createTweet(score) {
  return `■${dayjs.dayjs().format("M月D日")} APEXランク進捗
RankPoint : ${score.rankScore}RP (前日比 ${score.rankScoreChange})
ArenaPoint : ${score.arenaRankScore}AP (前日比 ${score.arenaRankScoreChange})

現在のバトロワランクは${score.rank}です。
現在のアリーナランクは${score.arena}です。

#apexps5 #apexps4
#APEXランク #APEXフレンド募集 #Apex募集
`
}

サクッと作れたんでbotで配信したいものがある人は手軽に作ってみるといいかもしれない。

さて。もう少しでソロダイヤ到達なんで今夜も頑張ろーっと。

この記事が気に入ったらサポートをしてみませんか?