[GAS]SlackのファイルをぜーんぶGoogleDriveへ無料アップロード!


こんにちは、美味しいしです。
今回がqiita初投稿なので、至らぬ点は多めにみてください。

はじめに

Slackをつかって仕事をする方、最近多いのではないでしょうか。
リアクションを飛ばせたり、チャンネルごとに通知設定ができたりと何かと便利なSlackですが、いつの間にか過去のファイルが消えていることがしばしば...
Freeプランのストレージが5GBしかないことが、過去事例の参照や引継ぎを困難にし、Slackの利便性を低めています。
なんとかならないものか...しかし金はかけたくない。

そこで、 Slackのファイルを丸ごとgoogleDriveにアップロード してしまおうと思います。
しかも、GASを使えば驚くほど簡単にしかもサーバーレスで書けるのです!

特にG Suiteを使っている方はgoogleDrive容量が十分あると思われるため、うってつけです!

Slack上のファイルを全てgoogleDriveにアップロードするコード

仕様

今回のシステムは、slack上の操作をトリガーにするのではなく、cronにより毎日実行するものです。叩くのもslackAPIのみとなります。
以下のように動作します。

  1. Slackのchannelのlistを取得。
  2. channelのIDと適切なタイムスタンプを用いて、欲しいfileのlistを取得。
  3. fileのプライベートURLを用いて,ファイルをchannelごとにGoogle Driveに保存する。
  4. 2~3を繰り返す。

準備

SlackのAccess Tokenの取得

Slackアプリをを作りましょう。
まずここにアクセスして新しいアプリを作成します。次にOAuth & Permissionsから、以下のスコープを追加します。

  • files:read ファイルの取得のために必要です。
  • channels:read チャンネルの取得のために必要です。

スコープを追加したら、忘れないうちにアプリをワークスペースにインストールしてしまいましょう。
ここででてくるOAuth Access Tokenは今後使います。
(それ以外は使いませんので、すでにSlackアプリを制作したことがある場合は既存のアプリに上記permissionを足してAccessTokenだけを使っても構いません。)

googleDriveのFolderIDの取得

次にGoogleDriveで使用するフォルダに移動します。

URLのfoldersの後の部分がFolderIDとなります。

プログラム

先ほど取得したAccessTokenは適宜「ファイル > プロジェクトのプロパティ > スクリプトのプロパティ」に「TOKEN」の名前で登録してください。アップロード先のGoogle DriveのFolderIDも同様に「FOLDER_ID」の名前で登録する必要があります。

fileApp.gs
function main(){
  var scriptProperties = PropertiesService.getScriptProperties();
  var slackAccessToken = scriptProperties.getProperty("TOKEN");
  var channelsRawData=UrlFetchApp.fetch('https://slack.com/api/channels.list?exclude_archived=true&token='+slackAccessToken)
  var channelsJson = JSON.parse(channelsRawData.getContentText());
  var channels = channelsJson.channels;
  for(var i = 0; i < channels.length; ++i){
   moveFiles(channels[i].id,channels[i].name); 
  }
}


function moveFiles(cid,cname){
  var scriptProperties = PropertiesService.getScriptProperties();
  var slackAccessToken = scriptProperties.getProperty("TOKEN");
  var folderId = scriptProperties.getProperty("FOLDER_ID");
  var dateUnix= parseInt(new Date() /1000) ;
  var dateS =dateUnix - 86400-3600;
  var dateE = dateUnix - 3600;
  var filesRawData=UrlFetchApp.fetch('https://slack.com/api/files.list?token='+slackAccessToken+'&channel='+cid+'&count=200&ts_from='+dateS+'&ts_to='+dateE);
//初めて実行するときに上記でなく
//var filesRawData=UrlFetchApp.fetch('https://slack.com/api/files.list?token='+slackAccessToken+'&channel='+cid+'&count=200');
//とすれば、全てのファイルを得られる。
  var filesJson = JSON.parse(filesRawData.getContentText());
  var files = filesJson.files;

  var rootFolder = DriveApp.getFolderById(folderId);
  var targetFolder = rootFolder.getFoldersByName(cname);
  if(targetFolder.hasNext() == false){
    var targetFolderId = rootFolder.createFolder(cname);
  } else {
    var targetFolderId = DriveApp.getFolderById(targetFolder.next().getId());
  }
  for(var i = 0; i < files.length; ++i){
    if (files[i].external_type != 'gdrive' && files[i].size<50000000){
      var timestamp = files[i].timestamp;
      var d = new Date(timestamp*1000);
      var date =Utilities.formatDate( d, 'Asia/Tokyo', 'yyyy-MM-dd-hhmm');
      var headers = {
        "Authorization" : "Bearer " + slackAccessToken
      };
      var params2 = {
        "method":"GET",
        "headers":headers
      };
      var dlData = UrlFetchApp.fetch(files[i].url_private, params2).getBlob();
      //yyyy-MM-dd-hhmmファイル名で保存している。
      dlData.setName(date+files[i].name);
      var driveFile = targetFolderId.createFile(dlData);
    }
  }
    Utilities.sleep(100);
}

定期実行


ここから、トリガーを追加して、動かしたい時間に動かせば、定期実行されます。
cronも簡単だね!

まとめ

GASで50行ちょいのコードでもSlackがより使いやすくなるので、ぜひ導入してみてください!

関連記事

Slackのストレージを消費せずにファイルをアップロード ~アップロードされたファイルを即座にGoogle Driveに転送する~
コードを書く時とqiitaを書くときに参考にさせていただきました。こちらの方は、即時応答のプログラムですね。