はじめに
Slackの新着絵文字をお知らせするBotをGASで作るの続きです👈
今回はSlack Enterprise Grid固有の機能を使って、さらに 絵文字で盛り上がるインターナルコミュニケーション
の活用を模索します。
今回のメニューはこんな感じです。
- 「この新着絵文字は誰が追加したのか」を可視化する
- その月・その週など特定の期間に作られた全絵文字を可視化する
- 「月間絵文字登録者ランキング」を作って社内を盛り上げる
尚、今回は Slack Enterprise Grid固有の機能を使います ので、Slack Enterprise Gridを契約されているワークスペースのみが対象となります。この点ご留意&ご了承ください。
それでは早速参りましょう。
今回のソースコードは 7032/gas_emojichecker_enterprise です。
「この絵文字は誰が追加したのか」を取得する
Slack Enterprise Grid 固有の機能のひとつとして Admin 向けAPI があります。これは Slack のかなりの機能について Rest API で色々な中身を取得できるAPI群です。その網羅範囲は、これらを利用する為だけに Slack Enterprise Grid を契約してもお釣りがくるレベルかと思います。
絵文字の詳細を取得する
その多機能なAdmin向けAPI群の一つがワークスペースに登録されている絵文字の詳細を含むリストの取得です。
Enterprise Grid 未満で使用できる emoji.list
というAPIもありますが、これは 登録されている絵文字の一覧を返すのみ です。
一方で、 admin.emoji.list
は、各絵文字を 「いつ」「誰が」登録したのか といった詳細も取得することが出来ます。
GET https://slack.com/api/admin.emoji.list
{
"ok": true,
"emoji": {
"workflow": {
"url": "https://emoji.slack-edge.com/TM315QLU8/workflow/530de66adccc59c5.png",
"date_created": 1591720632,
"uploaded_by": "WLWLQDAL9"
},
"welcome": {
"url": "https://emoji.slack-edge.com/TM315QLU8/welcome/763d3659699d2ef7.gif",
"date_created": 1593383451,
"uploaded_by": "WPU7MCTFH"
},
では早速これを活用して、現在あなたのワークスペースに登録されている全ての絵文字の情報を取得してみましょう。
admin.emoji.list を使う為の準備
admin.emoji.list
を呼ぶためには、Botに admin.teams:read
の権限が必要になります。
なのでまずはこの権限をBotに付与して、APIを使用できるOAuthトークンを取得しましょう。
- Bot選択画面Your Appsで、権限を付与するBotを選択する
-
OAuth & Permissions
を選択し、User Token Scopes に admin.teams:read を付与する - Botをワークスペースにインストールする
これで、APIを呼ぶための OAuth Token を取得できます。
尚、Bot User OAuth Token
なので、ワークスペースの管理者権限の方がログインした状態でOAuthによる「権限行使の承認」を行う必要があります。
OAuthでの承認が完了したら Bot User OAuth Token
にトークンが入りますので、スクリプトプロパティ に値を保存しておきましょう。
下記のソースコードでは api-token
という名前でスクリプトプロパティに保存されている前提としてあります。
// get current all emoji
function _peekAllCurrentEmoji() {
var allList = {};
var pageToken = "";
var fLoop = true;
const apiToken = PropertiesService.getScriptProperties().getProperty("api-token");
for(;fLoop;) {
var url = "https://slack.com/api/admin.emoji.list?limit=1000";
if (pageToken.length > 0) {
url += "&cursor="
+ pageToken;
}
const response = UrlFetchApp.fetch(
url,
{ "method" : "GET",
"headers" : {
"Authorization" : "Bearer " + apiToken
},
"muteHttpExceptions" : true
}
);
const resultTxt = response.getContentText();
const resultJson= JSON.parse(resultTxt);
pageToken = resultJson['response_metadata']['next_cursor'];
fLoop = false;
if (pageToken.length > 0) {
fLoop = true;
}
Object.assign(allList,resultJson['emoji']);
}
return allList;
}
上記は、シンプルに https://api.slack.com/methods/admin.emoji.list
を呼んで、その結果を全て結合して返しているのみです。
[https://api.slack.com/methods/admin.emoji.list
]は引数 limit
で指定した数までしか最大で値を返しません。Enterprise Gird ともなると 数百~数千の絵文字が登録されていることも珍しくない ので、APIを複数回呼ぶ必要があります。
取得した一覧は絵文字の名前をキーとして、その絵文字に関する詳細を値とする連想配列で格納されます。
{
"ok": true,
"emoji": {
"workflow": {
"url": "https://emoji.slack-edge.com/TM315QLU8/workflow/530de66adccc59c5.png",
"date_created": 1591720632,
"uploaded_by": "WLWLQDAL9"
},
....
}
上記の場合、キーとなる "emoji"
が絵文字名で、 Slack上の表現では :emoji: で表現される絵文字についての詳細となります。
値部分には以下が入ります。
キー | 値の内容 |
---|---|
url | 絵文字として登録された画像のURL。絵文字が画像の登録ではなくエイリアスの登録の場合は、"https://emoji...." という形式ではなく "alias:hoge" となり、hoge 部分がオリジナルの絵文字を指します。 |
date_created | その絵文字が登録された日時 (unix_time / UTC) |
uploaded_by | その絵文字を 登録したアカウントの Slack ID |
それでは、早速これを使って前回の Slackの新着絵文字をお知らせするBotをGASで作る を改良してみましょう。
まずは、更に以下の関数を追加します。
// get the Slack account who did register the emoji.
// propName : label of Script Property that stored the API token to access Admin API.
// emoji : emoji name
function _getOriginalRegistererOfEmoji(propName,emoji) {
const allList = _peekAllCurrentEmoji(propName); // 登録されている全部の絵文字を取得する
const result = allList[emoji]; // 指定された絵文字についての情報を取得する
if (result != null) {
if (result['uploaded_by']) {
return result['uploaded_by']; // どのアカウントが登録したかを返す
}
}
}
今回はシンプルに、一度全部の絵文字を取得した後に、その中から指定された絵文字についての情報を取得する様にしました。但し、あまりに多くの絵文字が登録されている場合、APIの呼び出し回数が多くなり、それだけ負荷もかかりますので、
- Event通知を或る程度溜めてから通知する
- 絵文字一覧は定期的に取得して別のDBへ保存するようにする
など工夫されると良いかと思います。
そして、取得したSlackアカウントをメッセージに挿入します。Slack ID は Incoming Webhook のメッセージ中で <@Slack ID>
という形式で挿入すると、実際のメッセージ上ではメンションとして表示されますので、今回はこれをそのまま活用します。
var strMessage= "*[New EMOJI]* :"+emojiName+": is added as *`:"+emojiName+":`*";
// 「この絵文字は誰が追加したか」の情報を付加する
const updateBy = _getOriginalRegistererOfEmoji("api-token",emojiName);
if (updateBy != null) {
strMessage += " by <@" // Slack ID がメンションとして表示されるようにする
+ updateBy
+ ">"
}
strMessage += "!!!\n";
これで
絵文字が新規で登録されたら「誰が登録したか」を含めて通知する Botの出来上がりです。😉
その月・その週など特定の期間に作られた全絵文字を可視化する
せっかく「誰が」「いつ」「どの絵文字を」登録したのかの一覧を取得できるようになりましたので、通知に使うだけでは勿体なく思いませんか?というわけで是非これを他にも活用してみましょう。
取得した絵文字を登録日時でふるいにかける
取得した全絵文字一覧には、その絵文字が登録された日時も unix time で取得できます。
この値を使って、全絵文字一覧から「今週」や「今月」登録されたものはどれ?と選別することが出来ます。まずは、この部分を作ってみましょう。
また、折角ですので登録したユーザー別に整理してみましょう。
function getEmojiRegistererDuringRange(range) {
// 全絵文字を取得
const allEmoji = peekAllCurrentEmoji('api-token');
var allCount = {};
// 取得した全絵文字を調べて条件に適合するものを抽出する
for(var key in this.allEmoji) {
const val = this.allEmoji[key];
const user = val['uploaded_by'];
// 絵文字名、url、登録日時を1つのオブジェクトとしてまとめる。
const item = {
"name": key,
"url": val['url'],
"date_created": val['date_created']
}
var fAdd = ((range == null) ? true : false);
// この絵文字は指定した範囲の日時に登録されたものであれば集める対象とする(fAddをtrueとする)
// range が指定されておらず null の場合は全ての絵文字を対象とする
if (range) {
if (item.date_created >= range) {
fAdd = true;
}
}
// 集める対象の絵文字を登録者のSlack ID別に配列に格納する
if (fAdd) {
const keys = Object.keys(allCount);
if (keys.indexOf(user) == -1) {
allCount[user] = [ item ];
} else {
allCount[user].push(item);
}
}
}
return allCount;
}
これで、下記のようなJSONを取得することが出来ます。
{ "<Slack ID 1>" :
[
{
"name" : "絵文字名"
"url" : "絵の元画像のURL,またはエイリアスの元の名前",
"date_created" : 1591720632 // 登録日時(unix time)
},
...
],
"<Slack ID 2>" : ...
...
}
「月間絵文字登録者ランキング」を作って社内を盛り上げる
特定期間に登録された絵文字を登録者別に取得することが出来ました。
これを「登録された数順に登録者を並び替える」ことをすれば「登録数ランキング」の出来上がりです。
var ranking = [];
// 上記で取得した「対象期間中の登録者別絵文字一覧」を一次配列とする
for(var i in allCount) {
const item = allCount[i];
ranking.push(
{ "owner": i,
"contents": item
}
)
}
// 登録されている絵文字の数順(降順)にソートする
ranking.sort(
function(a,b) {
const numA = a['contents'].length;
const numB = b['contents'].length;
return numB - numA;
}
);
return ranking;
これで、「登録された絵文字の数が多い順にソートされた登録者別の絵文字一覧」の配列が戻ってきます。
[
// 1位
{
"owner" : "<Slack ID>", // 登録者のSlack ID
"contents" : [ // その登録者が登録した絵文字一覧
{
"name" : "絵文字名"
"url" : "絵の元画像のURL,またはエイリアスの元の名前",
"date_created" : 1591720632 // 登録日時(unix time)
},
...
]
},
....
]
あとはこのJSONの中身をそのまま Incoming Webhook で通知すれば「絵文字登録数ランキング」を通知できますね。😉
const beginDate = new Date();
const lastMonth = beginDate.setMonth(beginDate.getMonth() - 1); // 1ヵ月前 = 月間ランキング.
const ranking = getEmojiRegistererRanking(lastMonth/1000); // msec to sec.
var strMsg = "*This month EMOJI register ranking!*\n";
for(var i in ranking) {
// show the registerer
strMsg += (Number(i)+1).toString()
+ " : <@"
+ ranking[i].owner
+ "> *("
+ ranking[i].contents.length
+ ")* = ";
// arrange all items those the ranker registered.
for(var j in ranking[i].contents) {
const item = ranking[i].contents[j];
strMsg += ":"
+ item.name
+ ": ";
}
strMsg += "\n";
}
sendMessageToSlack(
"incoming-webhook-url",
strMsg
)
さいごに
GASのトリガーで月初に登録しておくと、毎月頭に先月の「登録者数ランキング」が通知されます。
絵文字は登録数を競うものではないとは思いますが、コミュニケーションの目安として、また社内コミュニケーションを盛り上げるネタのひとつとして話題にするなどしてもらえば幸いです。
尚、今回 GitHub に登録しているソースは クラス化 してありますので、ご参考ください。
また、今回は社内で実際に利用しているコードを改変した上で私のプライベートアカウント上で公開しています。
※社内用のスクリプトは他の処理も含まれているため
もし「動かない」などありましたら、コメント頂くかプルリク頂けると色々な方が更に幸せになりますので、是非宜しくお願いします。🙇♀️