SlackAPIとGASを使用して管理者以外でもSlackチャンネル名変更できた

採用系のプロダクトを提供している会社でもろもろ担当~~する予定~~しているAkibinです。
ベースの基礎練習を怠っていたらちゃんと下手になったので、改めて基礎練習の大切さを痛感しているこの頃です。

# やってみたこと
Slackのチャンネル名はチャンネル作った人か管理者しか変更できません。
最近はチャンネルマネージャなるものをチャンネルにアサインできるのですが、それもそもそも管理者でないとアサインできないので既存のチャンネル全部にアサインできるかい！という感じでした。

ちょこちょこチャンネル名変更依頼が来るので、利便性向上から一般ユーザでもチャンネル名変更できるよう着手しますた。

# 参考資料
* [Slackのチャンネル名を管理者以外でも変更できるようにしてみた](https://moneyforward-dev.jp/entry/2021/03/22/rename-slack-channel/)
* [SlackAPI-conversations.rename](https://api.slack.com/methods/conversations.rename)

# 相棒
ChatGPT（GPT-4）と一緒に作成しました！プロンプトは以下。
```text
Google App Script、SlackのAPIとSlashコマンドを使用してSlackのパブリックチャンネルの
チャンネル名を変更する方法を教えてください
```
プロンプトが未熟だったからなのか、後述するコードでのトークン指定方法がうまくいかなかったり（Authorization: Bearerヘッダを使用しないといけなかった）、SlackAppのScope設定がGPT-4指示のだけだと足りなかったり、ちょいちょいこっちで調べたりは発生しましたが、それでも大まかな環境構築方法は相棒が賄ってくれたのでだいぶ楽できました。

# 流れ
1. SlackでAppを作成してスコープを設定、アクセストークンを取得
1. GASを作成、アクセストークンを設定、GASへのリクエストURLを取得
1. SlackAppでSlashコマンドを作成、GASのリクエストURLを設定。SlackAPPをSlackワークスペースにインストール
1. Slackで該当チャンネルにAppをインストールしてチャンネル名変更コマンド実行

# 作業
### SlackでAppを作成してスコープを設定、アクセストークンを取得
1. [SlackApp](https://api.slack.com/apps) > Create New App > From scratch でApp作成
1. OAuth & Permissions > User Token Scopes で以下を設定
    * channels:write
    * groups:write
    * im:write
    * mpim:write
1. OAuth Tokens for Your WorkspaceからUser OAuth Tokenをコピーしておく

### GASを作成、アクセストークンを設定、GASへのリクエストURLを取得
1. [Google App Script](https://script.google.com/home) > 新しいプロジェクトを作成 > 以下コードを貼り付けて保存
```javascript
function doPost(e) {
  const postData = e.postData.contents;
  const data = parseUrlEncodedData(postData);
  
  const scriptProperties = PropertiesService.getScriptProperties();
  const SLACK_ACCESS_TOKEN = scriptProperties.getProperty('API_KEY');
  const channelId = data.channel_id;
  const newChannelName = data.text;

  // Slack APIを呼び出してチャンネル名を変更する
  const apiUrl = `https://slack.com/api/conversations.rename`;
  const options = {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${SLACK_ACCESS_TOKEN}`,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify({
      channel: channelId,
      name: newChannelName
    })
  };

  const response = UrlFetchApp.fetch(apiUrl, options);
  const result = JSON.parse(response.getContentText());

  if (result.ok) {
    return ContentService.createTextOutput(JSON.stringify({ text: `チャンネル名が *${newChannelName}* に変更されました。` })).setMimeType(ContentService.MimeType.JSON);
  } else {
    return ContentService.createTextOutput(JSON.stringify({ text: `チャンネル名変更に失敗しました。指定した名前はすでに使用されていまふ` })).setMimeType(ContentService.MimeType.JSON);
  }
}

function parseUrlEncodedData(data) {
  return data.split('&').reduce((result, keyValue) => {
    const [key, value] = keyValue.split('=');
    result[decodeURIComponent(key)] = decodeURIComponent(value);
    return result;
  }, {});
}
```
1. 次にトークンを設定する。歯車マークのプロジェクトの設定 > スクリプトのプロパティの追加に以下を入力
    * プロパティ：API_KEY
    * 値：SlackAppでコピーしたトークン
2. エディタに戻り、デプロイを実施。ウェブアプリのURLをコピーする
    * 種類の選択：ウェブアプリ
    * アクセスできるユーザ：全員

### SlackAppでSlashコマンドを作成、GASのリクエストURLを設定。SlackAPPをSlackワークスペースにインストール
1.  [SlackApp](https://api.slack.com/apps) > Slash Commands > Create New Command
    * Command：任意のコマンド（例：rename-channels）
    * Request URL：GAS（ウェブアプリ）のURLを貼り付け
    * Usage Hint：入力のヒント（例：[新しいチャンネル名]）
2. OAuth & Permissions > OAuth Tokens for Your Workspace > Install to Workspace でAppをワークスペースへインストール

### Slackで該当チャンネルにAppをインストールしてチャンネル名変更コマンド実行
1. 以下方法で該当チャンネルにAppインストール(例：App名はchangeChannelName)
![スクリーンショット 0005-04-20 15.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/fa8530a0-4ef7-e2fb-98f0-c7441e0d158a.png)
2. チャンネル名変更実行
![スクリーンショット 0005-04-20 15.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/6e96cb1b-acbe-a8ff-1d5b-a91037d06652.png)
変更されました！
![スクリーンショット 0005-04-20 15.35.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/c2b919ad-4506-676e-d81e-43fa2aeb610a.png)

# こちらもチェックお願いします！
[Twitterアカウント](https://twitter.com/akibinmusic)
[Youtubeチャンネル](https://www.youtube.com/channel/UC-JOpwEnJn3gCrUA4NdCYgg)