マルチチャンネルゲストからシングルチャンネルゲストへの変更可能なSlackユーザーを洗い出す

## まえおき

- [Slackを導入していて気付いたいくつかの小さなこと（2018冬） - Qiita](https://qiita.com/mollinaca/items/1d1ca70d9972e1714c5f)

で「マルチチャンネルゲストからシングルチャンネルゲストへの自動降格」の箇所を読んでいて確かにそうだなと思ったので、本記事＆コードを書こうと思います。

※トークンなど秘匿箇所は「@@@@@」で明記しています。

## やりたいこと

1. マルチチャンネルゲストで、参加しているチャンネル数が1つだけのユーザーを洗い出す
2. 洗い出されたユーザーをマルチチャンネルゲストからシングルチャンネルゲストに変更する

SlackのAPIでシングルチャンネルゲストに変更する方法が見当たらなかったので、今回は１のみ対応しようと思います。


## 実践

### 実行環境
Node.js環境で実行しようと思います。
2018年12月19日現在で、実際に実行した環境のバージョンは次の通りです。

- Node.js ---> 10.8.0
- npm  ---> 6.1.0


### ソースコード
実際に使用した `package.json` と `index.js` は下記の通りです。

```json:package.json
{
  "name": "slack-guest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "check": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "async": "^2.6.1",
    "slack-node": "^0.1.8"
  }
}
```

```javascript:index.js
const Slack = require('slack-node');
const async = require('async');

const SLACK_TOKEN='＠＠＠＠＠ここにSlackから払い出したトークン＠＠＠＠＠';
const slack = new Slack(SLACK_TOKEN);

slack.api("users.list", function (err, res) {
    async.each(res.members, function(member, callback){
        if(!member.deleted && member.is_restricted && !member.is_ultra_restricted){
            let channel_list = member.profile.guest_channels.split(',');
            if(channel_list.length == 1){
                console.log(`${member.real_name}さんです。(${member.profile.email}|${member.profile.guest_channels})`);
            }
        }
    });
});
```

※SLACK_TOKENの箇所は、ご自身のSlackワークスペースから払い出したトークンを設定してください(`xoxb-〜〜〜`のトークンです)

1. 上記2つのファイルを任意のディレクトリに格納した後で `npm install` コマンドを実行してください。　※これは初回に1度だけで大丈夫です。
2. `node index.js` でメイン処理を実行してください。　※チェックを繰り返す際は、このコマンドだけを再実行してください。


### 実行結果

参加しているチャンネルが1つだけのマルチチャンネルゲストが存在した場合は、下記のような結果になります。対象者が複数人いれば、複数行結果が返ってきます。

```
名前さんです。(メールアドレス|["参加チャンネルID"])
```

※`console.log`の出力内容はお好みで変更しても問題ありませんが、同姓同名や類似の名前で間違えないために、メンバー管理画面でアカウント変更する際は**メールアドレス**で絞り込んでから変更することをオススメします。


## やってみて気付いたこと

### 使用するAPIは `users.list` だけで完結できた

SlackのAPIの `users.list` と `channels.list` のメソッドを使って、ユーザーと参加チャンネルの突き合わせをしようと試みたところ、 `users.list` のレスポンスの中に `guest_channels` という項目があり、そこにゲスト参加しているチャンネルIDが配列で格納されていることに気付きました。

`users.list` の [Documentation](https://api.slack.com/methods/users.list) には `guest_channels` の記載がなかったので、実際に [Tester](https://api.slack.com/methods/users.list/test) にてテスト実行して存在をご確認いただければと思います。

これにより使用するAPIは `users.list` だけで完結できました。

ただし `guest_channels` はゲストアカウントのユーザーにしか表示されないので、アカウントの種別を見分ける必要があります。(後述)


### ゲストアカウントの見分け方

こちらも `users.list` の結果から見分けることが可能です。


```json:users.listのレスポンス結果
{
    "ok": true,
    "members": [
        {
            "id": "@@@@@@@@@@",
            "team_id": "@@@@@@@@@@",
            "name": "@@@@@@@@@@",
            "deleted": false,
            ・・・(略)・・・
            "is_admin": false,
            "is_owner": false,
            "is_primary_owner": false,
            "is_restricted": true,
            "is_ultra_restricted": false,
            "is_bot": false,
            "is_app_user": false,
            ・・・(略)・・・
        },
        ・・・(略)・・・
```

| 項目                 | ①シングル | ②マルチ | 説明                     |
|---------------------|----------|---------|-------------------------|
| is_admin            | false    | false   | アドミンかどうか             |
| is_owner            | false    | false   | オーナーかどうか            |
| is_primary_owner    | false    | false   | プライマリーオーナーかどうか    |
| is_restricted       | **true**     | **true**    | ゲストアカウントかどうか  |
| is_ultra_restricted | **true**     | false   | シングルチャンネルゲストかどうか |
| deleted             | false    | false   | 無効化ユーザーかどうか  |

有効なマルチチャンネルゲストのみに絞り込みたいときは、下記を条件に絞り込みます。

- `"is_restricted": true` でかつ `"is_ultra_restricted": false` であること
- また無効化済みユーザーは除外したいため、 `"deleted": false`であること

↓↓↓

```
if(!member.deleted && member.is_restricted && !member.is_ultra_restricted){
```


## 参考情報

- [Slackを導入していて気付いたいくつかの小さなこと（2018冬） - Qiita](https://qiita.com/mollinaca/items/1d1ca70d9972e1714c5f)
- [users.list - Slack API]
(https://api.slack.com/methods/users.list)

## あとがき
実際に仕事先のSlackワークスペースに対して実施してみたところ、【**5人**】見つかりました :innocent:
@mollinaca さん、新しい気付きをありがとうございました :relaxed: