MSFlowとGASとTwitterで行う簡単課金額計算と通知機能の実装

# はじめに
私はプログラミング初心者です、温かい目で見てください。

# この記事はなに？
Twitterの特定ハッシュタグをつけてツイートされた課金額を、GoogleスプレッドシートにFlowを用いて書き込みを行い
そこからGASで特定のユーザーに対して課金額の合計値を通知するようにしてみました。
その備忘録の内容となります。

備忘録のため、専門的な内容には触れず（難しいことわかりません）必要最低限のメモレベルで残したいと思います。

## 準備
### 必要なもの
・Microsoftアカウント（Flowの作成に使います）
・Twitterアカウント（ツイッターの投稿内容の取得、通知に使います）
・Googleアカウント(スプレッドシート作成とGAS作成に使います）

---------------------------------------------------------------------------------------------------
## 実践
### **ステップ1. Googleスプレッドシートを作る**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/263877/1f3b5510-f104-c926-faee-7f5542ccd92b.png)
■予め「名前」「日時」「内容」列を作成します。(それ以外は触らないで大丈夫です）
（PowerAppsIDはデフォルトで作成されるため作らなくて大丈夫です）
（また中身は既に運用中のものなのでモザイク加工をしています）

### **ステップ2. Flowの設定**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/263877/b2f58082-1b2c-2238-0e0a-0255e9059b8f.png)
■MSFlowのアクション・トリガーという概念を用いて、ツイッターの特定ハッシュタグにツイートがあった場合は
　そのツイートの投稿者名を確認し、特定の文字列が含まれていたらスプレッドシートに
　その「名前」「日時」「内容」を追記する、というような設定を上記では行っています。

#### **結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/263877/1a47ba37-bf9f-7e72-dde7-b61fc2c44712.png)
■自動的にハッシュタグの中身をFlowが確認し、条件に一致していた場合はGoogleスプレッドシートに追記を行えました。

### **ステップ3. GASのプログラミング**
ここまでで、スプレッドシートに対してデータの書き込みが行えるようになりました。
次はスプレッドシートに対して更新がかかったら、その都度課金額を計算する仕組みを用意します。

■ポイント
1. 月単位で計算を行いたい
2. スプレッドシートにはユーザーの入力した文字列が入るため単純な金額だけが表示されるわけではない
3. 稀にユーザー名が類似している方が同一ハッシュタグを使ってツイートする可能性がある

**1. 月単位で計算を行いたい**
累計課金額を通知する場合は考慮しなくても良いが、月単位の課金額を知りたい場合はプログラム実行時の月を取得し
それをもとに日時列の比較を行う必要がある。

**2. スプレッドシートにはユーザーの入力した文字列が入るため単純な金額だけが表示されるわけではない**
基本的には　ゲーム名　金額(3000など)　#固定ハッシュタグ名　の組み合わせが1ツイートとなる。
そのためスプレッドシートかGAS側で金額だけを抽出できるようにする必要がある。

**3. 稀にユーザー名が類似している方が同一ハッシュタグを使ってツイートする可能性がある**
条件文にユーザ名で「test」を「含む」などにしてしまった場合、類似ユーザーがハッシュタグを利用してしまうと
計算結果に誤りが出てしまう可能性がある。（ここは予めユーザ名を変えないようにするか、複数条件にする必要がある）
まぁここはあまり厳密には今回考えず・・。

---
#### **とりあえず実装チャレンジ**
``` GASによる当年と当月取得(便宜上jsとつけています).js
// 「年」「月」取得
function getNowDate(){
  var NowDate = new Date();
  NowMonth = ((NowDate.getMonth() + 1) < 10) ? "0" + (NowDate.getMonth() + 1) : (NowDate.getMonth() + 1);
  NowYear  = NowDate.getYear() + ".0";
}
```

``` GASによる日付列の判定(便宜上jsとつけています).js
// 行数分ループで日付判定する
function getNowMonthLine(sheet){
  // 最終行を取得
  var lastLine = sheet.getLastRow();
  
  // 正規表現で金額抽出を行うためのスプレッドシート（エクセル）関数を追加する
  addMoneyCalcFunc(sheet, i);

  // 行数分ループを回す
  for(var i = 2; i <= lastLine; i++) {
    Logger.log(Utilities.formatDate(new Date(sheet.getRange(i, 2).getValue()), "JST", "YYYY.0MM"));
    
    // スプレッドシートの日時列と当年、当月の比較
    if(Utilities.formatDate(new Date(sheet.getRange(i, 2).getValue()), "JST", "YYYY.0MM") === (NowYear + NowMonth)){
      // 当月の行数Noを格納
      DayData.push(i);
      Logger.log(i + "行目が当月分");
    }
  }  
}
```

``` GASによる内容列にある数字を抽出する正規表現追加関数(便宜上jsとつけています).js
// すべての列に正規表現で金額抽出を行うためのスプレッドシート（エクセル）関数を追加する
function addMoneyCalcFunc(sheet, LineNo){
  sheet.getRange("F" + LineNo).setValue("=IFERROR(VALUE(REGEXEXTRACT(C" + LineNo + ",\"\[0123456789,-\]\{1,\}\")),0)");
}
```

``` GASによる名前列のチェック(便宜上jsとつけています).js
var CHECK_NAME = "UserName";
// 当月と判定された列のユーザー名を確認する
function checkUserName(sheet){
  // リストの数だけ判定
  for(var i = 0; i < DayData.length; i++){
    
    Logger.log(sheet.getRange(DayData[i], 1).getValue());
    
    if(CHECK_NAME === (sheet.getRange(DayData[i], 1).getValue())){
      Logger.log(DayData[i] + "行目が課金計算対象");
      CheckLine.push(DayData[i]);
    }else{
      Logger.log(DayData[i] + "行目は[UserName]以外のユーザーがハッシュタグ使っているようです");
    }
  }
}
```

``` GASによる合計金額の加算処理(便宜上jsとつけています).js
// 合計金額の加算処理
function TotalMoneyCheck(sheet){
  var TotalMoney = 0;
  
  for(var i = 0; i < CheckLine.length; i++){
    TotalMoney += sheet.getRange(CheckLine[i], 6).getValue();
  }
  
  return TotalMoney;
}
```

``` GASからTwitterへのポストをするための処理(便宜上jsとつけています).js
// GAS -> Twitterのためのライブラリ
// 参考：https://qiita.com/expajp/items/7cc16378ee790f1d404f
function tweetMoneyPost(Money){
  Logger.log(NowYear + "年" + NowMonth + "月の課金額：" + Money + "円");

  Twitter.tweet({ status: "@" + CHECK_NAME + " " + NowYear + "年" + NowMonth + "月の課金額：" + Money + "円"});
}
```

基本的にツイッター連携とPOSTに関してはこちらの記事の内容をそのまま実行させていただきました
[【Twitter】GASで自分のツイートを定期RT/引用するbotを作った](https://qiita.com/expajp/items/7cc16378ee790f1d404f)

■とりあえず結果としてTwitterアプリケーションはこんな感じ
![image.png](https://i.gyazo.com/96460757869d20afa5781681df6739d1.png)

``` GASによるメインの関数(便宜上jsとつけています).js
// メイン関数
function myFunction() {
  // スプレッドシートの指定
  var spreadsheet = SpreadsheetApp.openById('シートのURLのそれっぽい文字列');

  // スプレッドシート -> シートを指定
  var sheet = spreadsheet.getSheetByName('シート名');
  
  // いま何月なのかを判断
  getNowDate();
  
  // スプレッドシート上の日付列から当月の行Noを取得する
  getNowMonthLine(sheet);
  
  // 当月の行のユーザー名を取得し、こちらが想定しているユーザーか否かを全て判定する
  checkUserName(sheet);
  
  // 当月&想定ユーザーの課金額を計算していく
  var NowMonthTotalUsageMoney = TotalMoneyCheck(sheet);
  
  // 金額通知
  tweetMoneyPost(NowMonthTotalUsageMoney);
}
```

GASの実行条件を「スプレッドシートから」「値の変更」が行われたら実行するように設定して完成。

### **結果**
①特定ユーザーが金額をハッシュタグをつけてツイート
②Flowが15分に1回ハッシュタグのツイートが更新されていないかをチェック
③更新されていて、かつこちらが指定したユーザーであればスプレッドシートにデータを追記
④追記されたというイベントから、GASが実行され、当月の課金額が通知されるようになった

![image.png](https://qiita-image-store.s3.amazonaws.com/0/263877/f1f12519-101c-e963-55f8-4f12bac6da3f.png)
■実際のPOST内容

### **まとめ**
なんかノリで適当にはじめてみましたがなかなかおもしろかったです。
かなり手順とか端折ってしまっていますが何となく伝わっていただければ幸いです。
プログラミング初心者のためやっちゃダメなことやってるかもしれませんが生暖かい目で見て下さい＞＜；