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の処理がとても大変だった.なんかもっとうまい書き方をしたい(切実).