LoginSignup
5
5

More than 3 years have passed since last update.

Slack APIを使ってユーザーグループのメンバーをCSVからまとめて追加する

Last updated at Posted at 2019-06-09

Slackのユーザグループ管理が面倒なのでなんとか楽にしようとしてみた.
今回やりたいことのイメージはGSuiteのユーザー追加のときみたいに,CSVを読み込んでまとめてメンバーを追加する.

最低限の動作確認しかしていないので,使用するときは自己責任で.
(使用してる関数が,以前のグループメンバーに上書きされるのでとても注意)

追記:Slackの名前にはfullname, displaynameなどたくさんあって,一意にもとめにくかったのでemailで追加できるうように変更しました.

参考資料

https://api.slack.com/methods
https://api.slack.com/apps/AK24J41GT/oauth?success=1

環境

MacOS Mojave 10.14.5
Python3.7
slackclient 2.0.1

ユーザグループのメンバーの出力

まずは現在存在するユーザグループとその中にいるユーザをまとめてCSVに出力する.

使用したScope

  • usergroups:read
  • usergroups:write
  • users:read
  • users:read.email

ソースコード

インポートと関数定義

import os
import slack
import json
import pandas as pd
import datetime

LOG_PATH = 'log/'
USERGROUP_PATH = 'usergroups/'
if not os.path.exists(LOG_PATH): os.mkdir(LOG_PATH)
if not os.path.exists(USERGROUP_PATH): os.mkdir(USERGROUP_PATH)


def get_usergroups_list(client):
    user_groups = client.usergroups_list()
    if user_groups['ok']:
        return user_groups['usergroups']
    else:
        assert user_groups['ok']
        return None


def get_users(client):
    userdata = client.users_list()
    if userdata["ok"]:
        return userdata['members']
    else:
        assert userdata['ok']
        return None


def get_usergroups_member(client, user_groups_id):
    member = client.usergroups_users_list(usergroup=user_groups_id)
    if member['ok']:
        return member['users']
    else:
        assert member['ok']
        return None

メイン関数(もっと上手く書きたい)
今回は必要そうなデータだけとって出力するようにした.

if __name__ == '__main__':
    client = slack.WebClient(token=os.environ['SLACK_API_TOKEN'])

    users = get_users(client)
    user_groups = get_usergroups_list(client)

    df_users = pd.DataFrame(users)
    df_user_groups = pd.DataFrame(user_groups)

    # get current users who are in each user group
    for group_id in df_user_groups['id']:
        group_members = get_usergroups_member(client, group_id)
        save_data = pd.DataFrame({},
                                 columns={'group_id', 'group_name', 'user_id', 'user_name', 'user_real_name', 'email'})
        save_data['group_id'] = [group_id] * len(group_members)
        save_data['group_name'] = list(df_user_groups[df_user_groups['id'] == group_id]['name'].values) * len(
            group_members)
        save_data['user_id'] = df_users[df_users['id'].isin(group_members)].loc[:, 'id'].values
        save_data['user_name'] = df_users[df_users['id'].isin(group_members)].loc[:, 'name'].values
        save_data['user_real_name'] = df_users[df_users['id'].isin(group_members)].loc[:, 'real_name'].values
        save_data['email'] = df_users[df_users['id'].isin(save_data['user_id'])]['profile'].values
        save_data['email'] = save_data['email'].apply(lambda x: x['email'])
        save_data.to_csv(USERGROUP_PATH + "usergroups_" + save_data['group_name'][0] + "_list.csv")

ユーザグループのメンバーの追加

形式の決定

CSVの形式は次のようにした.

Group Name User EMAIL
Test1 Mr. Test1
Test1 Mr. Test2
Test1 Mr. Test3
Test1 Mr. Test4

この形式のCSVを読み込んでそれぞれのユーザグループにユーザを追加していく.
内部でIDとの紐付けを行い,最終的にAPIに送るのは以下のテーブル

Group ID Group Name User ID User EMAIL
T04J043MC Test1 T04J041MC Mr. Test1
T04J043MC Test1 T04J042MC Mr. Test2
T04J043MC Test1 T04J043MC Mr. Test3
T04J043MC Test1 T04J044MC Mr. Test4

ユーザグループが存在しないときはエラーとしてログに吐き出すようにする.

ソースコード

def usergroups_users_update(client, user_group, users):
    update = client.usergroups_users_update(usergroup=user_group, users=users)
    log = "upload_log" + datetime.datetime.today().strftime("%Y%m%d_%H%M%S") + ".txt"
    if update['ok']:
        with open(LOG_PATH + log, "w") as f:
            f.write("uploaded to {0} correctly: {1}".format(user_group, update['usergroup']['users']))
        return update['usergroup']
    else:
        assert update['error']
        with open(log, "w") as f:
            f.write("Error: {0}".format(update['error']))
        return None

if __name__ == '__main__':
    filename = "template.csv"
    filelist = glob.glob("template/*")

    client = slack.WebClient(token=os.environ['SLACK_API_TOKEN'])
    # ユーザのemailとIDとの紐付けを取得
    users = get_users(client)
    df_useremails = pd.DataFrame(users)

    # print(template)
    # ユーザグループの名前とIDとの紐付けを取得
    user_groups = get_usergroups_list(client)
    df_user_groups = pd.DataFrame(user_groups)
    for filename in filelist:
        if filename in ['template/template_CMAll.csv', 'template/template_tokyoCMAll.csv',
                        'template/template_tokushimaCMAll.csv', 'template/template_onagawaCMAll.csv',
                        'template/template_obuseCMAll.csv', 'template/template_tfcs.csv', ]:
            continue
        print(filename)
        template = pd.read_csv(filename)
        # 更新したいユーザグループIDとユーザーIDをグループ名とユーザー名と対応させる
        upload_data = pd.DataFrame({}, columns={'usergroup_id', 'usergroup_name', 'user_id', 'user_email'})
        upload_data['usergroup_name'] = template['usergroup_name'].values
        upload_data['user_email'] = template['user_email'].values
        upload_data['usergroup_id'] = template.apply(
            lambda x: df_user_groups[df_user_groups['name'].isin(template['usergroup_name'])]['id'], axis=1
        )
        tmp = pd.DataFrame(list(df_useremails['profile']))

        upload_data['user_id'] = df_useremails[tmp.loc[:, 'email'].isin(template['user_email'])].loc[:, 'id'].values
        upload_data = upload_data.groupby('usergroup_id')['user_id'].apply(",".join)
        print(len(upload_data))
        # 更新(以前のユーザーリストは消滅して新しく作成される)
        for key, value in upload_data.items():
            usergroups_users_update(client, key, value)

tmplate.csvに先ほどの2列のテーブルを作成すれば既存のグループメンバーを更新することができる.

pandasの処理がとても大変だった.なんかもっとうまい書き方をしたい(切実).

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5