gasでちょっとしたdiscord botを作成

**僕のハマっている[ゲーム](https://www.ubisoft.co.jp/r6s/)（FPS）には練習モードがありまして、**
**そのモードをどうやら僕はたくさんやっているようで、**
**1日どれくらいやってるのか、友人とどれくらい差があるのか**

**を知りたくなりました。**

---

なので、今回はゲームのマッチング待ち時間を利用してdiscordのbotを作成してみました。
gasで簡単にスケジュール実行ができると聞いたので、gasでやりました。

# 仕組み

https://r6tab.com/
↑はそのゲームの統計を見るサイトです（非公式）

その[API](https://github.com/Tabwire/R6Tab-API)を利用して統計を取得しています。

1. スプレッドシートからユーザー名を取得
2. ユーザーのプレイヤーIDを取得、練習モードのキル数を取得
3. スプレッドシートの値と比較して差分を計算
4. 諸々をテキストにしてDiscordに投稿

といった流れをスケジュール実行しています。

# 実行結果

<img width="429" alt="スクリーンショット 2020-01-15 15.12.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/5b59dbd9-0f48-8437-f8fd-e49b42ccc6b7.png">
_自分のユーザー名以外は一応隠しています。_

ユーザー名と総キル数、昨日との差分を表示しています。

# スプレッドシート

<img width="223" alt="スクリーンショット 2020-01-15 14.55.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/8a993a1f-9b3f-04ae-e876-2f93c402be0b.png">
_自分のユーザー名以外は一応隠しています。_

A列にユーザー名
B列にキル数（初回登録時は0）
を設定する。

# ソースコード

```javascript
function main() {
  // チェックするユーザー, キル数を取得
  var sheet = SpreadsheetApp.getActiveSheet();
  var users = sheet.getRange('A:A').getValues();
  var count = users.filter(String).length;  // ユーザー数
  var beforeKills = sheet.getRange('B:B').getValues();

  var messages = [];

  for (var i = 0; i < count; i++) {
    var id = getPlayerId(users[i]);
    if (!id) {
      messages.push('このユーザー名は存在しません。');
      continue;
    }
    var currentKills = getThuntKills(id);

    // 差分計算
    var diff = Number(currentKills) - Number(beforeKills[i]);
    diff = Math.floor(diff);

    messages.push('総キル数: `' + currentKills + '`\n 前回との差分: `' + diff + '`');
    // スプレッドシートの更新
    sheet.getRange('B' + (i + 1)).setValue(currentKills);
  }

  // キル数でソート
  sort();

  var text = createText(count, users, messages);
  postDiscord(text);
}


/**
 * プレイヤーIDを取得する
 *
 * @param {String} username - ユーザー名
 * 
 * @returns String プレイヤーID
 */
function getPlayerId(username) {
  var url = 'https://r6.apitab.com/search/uplay/' + username;
  var response = UrlFetchApp.fetch(url);
  var content = JSON.parse(response.getContentText('UTF-8'));
  // 存在しないユーザーを確認
  if (content['foundmatch'] === false) { return false; }
  var p_id = Object.keys(content['players'])[0];

  return p_id;
}


/**
 * テロハントのキル数を取得する
 *
 * @param {String} id - プレイヤーID
 * 
 * @returns Number キル数
 */
function getThuntKills(id) {
  var url = 'https://r6.apitab.com/player/' + id;
  var response = UrlFetchApp.fetch(url);
  var content = JSON.parse(response.getContentText('UTF-8'));
  var kills = content['stats']['generalpve_kills']

  return kills;
}


/**
 * 投稿するメッセージを作成する
 *
 * @param {Int} count - ユーザー数
 * @param {Array} users - ユーザー
 * @param {Array} messages - メッセージ
 * 
 * @returns Object - 投稿するメッセージ
 */
function createText(count, users, messages) {
  var results = [];

  for (i = 0; i < count; i++) {
    results[i] = {
      'name': users[i][0],
      'value': messages[i],
      'inline': true
    };
  }

  var text = {
    "embeds": [
      {
        "color": 15105570, // orange
        "fields": results
      }
    ]
  };

  return text;
}


/**
 * Discordに投稿する
 *
 * @param {Object} text - 投稿するメッセージ
 */
function postDiscord(text) {
  var url = 'https://discordapp.com/api/webhooks/000000000000/xxxxxxxxxxxxxxxxxx';

  var params = {
    'method': 'POST',
    'headers': { 'Content-type': 'application/json' },
    'payload': JSON.stringify(text)
  };

  UrlFetchApp.fetch(url, params);
}


/**
 * キル数でソートをする
 */
function sort() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var range = sheet.getRange("A:B");
  range.sort([{ column: 2, ascending: false }]);
}

```

# 実行トリガー

<img width="725" alt="スクリーンショット 2020-01-15 16.14.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/bb9d4137-4af1-8af4-75f9-30fe5533fb0f.png">

選ぶだけですが朝９時くらいに投稿される様にしました。

# 感想

- 簡単にbot?をつくることができた。
- 確かに友人より多くやっていることがわかった。
- このモードを多くやってるからといって強くなるわけではないことがわかった。

# 未来の自分へ

- 他鯖でも使用できるように、シートの追加の対応
- セキュリティ的にwebhook urlを隠す
- ソートのタイミングが1日遅いのを修正

をやってください。

# リンク

[rainbow six siege](https://www.ubisoft.co.jp/r6s/)
[使用したAPI](https://github.com/Tabwire/R6Tab-API)
[discord webhook document](https://discordapp.com/developers/docs/resources/webhook)