Slackにアップされたファイルを定期的に自動削除する(プライベートチャンネル対応)

# 仕様
パブリックチャンネルと**自分が参加する**プライベートチャンネルにアップされた、直近1週間以前のファイルを自動的に削除します
# 環境
Google Apps Script
Slack API
# Slack APIの準備
はじめにSlack APIの準備、丸投げですみませんがとてもわかりやすいので以下の記事を参照してください。
[Slack API 推奨Tokenについて #Tokenを作成する](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21#tokenを作成する)
今回利用したスコープはこちら

- channels:read  
- groups:read  
- files:read  
- files:write:user

# スクリプト
SlackのトークンはGASの「プロジェクトのプロパティ」に設定しています。

> 取得したトークンはプロジェクトのプロパティとして保存しておきましょう。
> メニューの「ファイル」→「プロジェクトのプロパティ」→「スクリプトのプロパティ」からSLACK_ACCESS_TOKENとして保存します
[初心者がGASでSlack Botをつくってみた](https://tech.camph.net/slack-bot-with-gas/)

channels:read, groups:readの2つのスコープとSlack APIの conversations.listメソッド でパブリックチャンネルとプライベートチャンネルを一気に取得できます。

```javascript:コード.gs
function myFunction() {
  channelsList();
}

/* チャンネルリストを取得 */
function channelsList() {
  var method = 'conversations.list';
  var params = '&types=public_channel,private_channel';
  var list = useSlackApiGet(method, params);
  if (list.ok) {
    list.channels.forEach(filesList);
//    list.channels.forEach(function(channel){
//      Logger.log(channel.name+'['+channel.id+']');
//    });
  }
}

/* チャンネル内のファイルリストを取得 */
function filesList(channel) {
//  Logger.log('##### '+channel.name+' #####');
  const days = 7; // n日以前のファイルを削除対象とする
  var method = 'files.list';
  var params = '&channel=' + channel.id;
  params += '&ts_to=' + daysToUnixTime(days);
  params += '&count=1000';
  var list = useSlackApiGet(method, params);
  if (list.ok) {
    list.files.forEach(deleteFile);
//    list.files.forEach(function(file){
//      Logger.log(file.name+'['+file.id+']['+file.filetype+']['+new Date(file.timestamp*1000)+']');
//    });
  }
}

/* ファイルの削除 */
function deleteFile(file) {
  var method = 'files.delete';
  var data = {'file': file.id}
  var res = useSlackApiPost(method, data);
  Logger.log(res);
}

/* 経過日数を指定する */
function daysToUnixTime(days){  
  var date = new Date();
  var now = Math.floor(date.getTime()/ 1000); // unixtime[sec]
  return String(now - 8.64e4 * days); // 8.64e4[sec] = 1[day] 文字列じゃないと動かないので型変換している
}

/* Slack APIを実行(GET) */
function useSlackApiGet(methodUrl, data) {
  var token = PropertiesService.getScriptProperties().getProperty("SLACK_ACCESS_TOKEN");
  var apiUrl = 'https://slack.com/api/';
  var params = '?token='+token+data;
  var res = UrlFetchApp.fetch(apiUrl + methodUrl + params);
  return list = JSON.parse(res.getContentText());
}

/* Slack APIを実行(POST) */
function useSlackApiPost(methodUrl, data) {
  var token = PropertiesService.getScriptProperties().getProperty("SLACK_ACCESS_TOKEN");
  var apiUrl = 'https://slack.com/api/';
  var headers = {
    'Content-type': 'application/json',
    'Authorization': 'Bearer '+token,
  };
  var options = {
    'method': 'POST',
    'headers': headers,
    'payload': JSON.stringify(data),
  };
//  Logger.log(UrlFetchApp.getRequest(apiUrl + methodUrl, options));
  return UrlFetchApp.fetch(apiUrl + methodUrl, options);
  
}
```
# GASのトリガー設定
最後にGASで起動トリガーを設定して完了です、こちらも丸投げですみません。
[Google Apps Script で毎日決まった時刻にスクリプトを実行するトリガー設定](https://tonari-it.com/gas-trigger-set/)
# 問題点
削除は正常に行われるのですが、files.deleteのレスポンスでwarningが出ます

```
{
    "ok":true,
    "warning":"missing_charset",
    "response_metadata":{
        "warnings":["missing_charset"]}
}
```
files.deleteのリクエスト内容はこんな感じ

```
{
    headers={
        Authorization=Bearer xoxp-XXXXXXXXXX, 
        X-Forwarded-For=XXX.XXX.XXX.XXX}, 
    method=post, 
    payload={"file":"XXXXXXXXXX"}, 
    followRedirects=true, 
    validateHttpsCertificates=true, 
    useIntranet=false, 
    contentType=application/json, 
    url=https://slack.com/api/files.delete
}
```
対処法などありましたらコメントいただけると助かります。
ありがとうございました。

# 参考サイト
[公式 Slack Web API](https://api.slack.com/web)
[Qiita Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)
[Qiita Slackのファイルを一気に削除する](https://qiita.com/9umaske/items/49bc1bd89330fe946ff3)
[Qiita Slackでファイルを削除するBotを作成した](https://qiita.com/yoccan/items/46b2a068807d79b59a61)
[Google Apps Script で毎日決まった時刻にスクリプトを実行するトリガー設定](https://tonari-it.com/gas-trigger-set/)