Open2
🍊Slack×GAS:チャンネル名をリネームしたい
ピン留めされたアイテム
ハマったので供養。
やりたいこと
スラッシュコマンドから発火し、特定のチャンネルをリネームしたい
実現イメージ
-
/rename [対象チャンネル名] [新名]
一致するチャンネルがリネームされる -
/rename [新名]
実行したチャンネルがリネームされる
想定の流れ
- スラッシュコマンド実行
- GASで受付:doPost(e)
- コマンドの引数に応じて分岐
- 対象のチャンネルを判別してリネーム
- 完了
これでいけるはずだったのに...
未解決課題
- チャンネルリネームにはチャンネルのオーナーor作成者orワークスペース管理者である必要がある
- bot、アプリからのユーザー代理操作は受け付けない
解決済課題
-
conversations.renameAPI実行時に
not_in_channel
が返る- 原因:BotUserが対象チャンネルに属している必要がある
-
conversations.list API実行時に
invalid_auth
が返る- → authの範囲を追加する必要がある
ソースコード(未リファクタ)
メイン関数
function doPost(e){
var verificationToken = e.parameter.token;
if (verificationToken != 'xxxxxxxxxx') { // AppのVerification Tokenを入れる
throw new Error('Invalid token');
}
var command = e.parameter.command;
var text = e.parameter.text;
var userId = e.parameter.user_id;
var commandAtChannelid = e.parameter.channel_id;
switch(command){
case '/addch':
try{
var addCh = createChannels(text)
var addRes = addUserToChannels(userId,addCh);
if( addRes!=false){
var response = {text:text + 'チャンネルを作成しました:https://pleiades-lab.slack.com/archives/'+addCh};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
var kekka2 = '作成できませんでした'
var response = {text:text + 'chを作成できませんでした'};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
catch(addchError){
var kekka2 = '作成できませんでした:' + error;
var response = {text: kekka2};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
break;
case '/renamech':
try{
if ( text.match(/ /)) {
//textに区切り文字を含む場合の処理
const array = text.split(' ');
const newName = array[0];
const targetCh = array[1];
//targetChで対象のチャンネルを検索
var targetChId = searchChannels('',targetCh);
}
else{
const newName = text;
var targetChId = commandAtChannelid;
}
const resultRename = renameChannels(targetChId);
if( resultRename == true){
var response = {text:'Rename Finished.'};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
else{
var response = {text:'Rename Failed.'+ resultRename};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
}
catch(renamechError){
var response = {text:text + renamechError.message};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
break;
default:
var response = {text:text + '分岐しませんでした'};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
break;
}
}
チャンネル検索用関数
function searchChannels(cursor,chName) {
const slack_app_token = "xoxb-xxxxxxxxxxxxxx";
const limit =500;
const options = {
"method" : "get",
"contentType": "application/x-www-form-urlencoded",
"payload" : {
"token": slack_app_token,
"cursor": cursor,
"limit":limit
}
};
const url = "https://slack.com/api/conversations.list";
const response = UrlFetchApp.fetch(url, options);
var channels = JSON.parse(response).channels;
for (const channel of channels){
if (channel.name == chName) {
Logger.log(channel.id)
return channel.id;
}
}
if( responseMeta = JSON.parse(response).response_metadata.next_cursor != ''){
searchChannels(JSON.parse(response).response_metadata.next_cursor,chName);
}
Logger.log('null');
return null;
}
チャンネル名を変更する関数
function renameChannels(chId,name){
addUserToChannels('botUserId',chId); // 作業対象チャンネルにBotユーザーを追加する
const slack_app_token = "xoxb-xxxxxxxxxxxxxx";
const options = {
"method" : "POST",
"contentType": "application/x-www-form-urlencoded",
"payload" : {
"token": slack_app_token,
"channel": chId,
"name": name
}
};
const url = "https://slack.com/api/conversations.rename";
try{
const response = UrlFetchApp.fetch(url, options);
const resText = JSON.parse(response).channel;
Logger.log(response);
const chId = resText.id;
return true
}
チャンネルにユーザーを追加する関数
function addUserToChannels(userId,chId){
const slack_app_token = "xoxb-xxxxxxxxxxxxxx";
const options = {
"method" : "POST",
"contentType": "application/x-www-form-urlencoded",
"payload" : {
"token": slack_app_token,
"channel": chId,
"users": userId
}
};
const url = "https://slack.com/api/conversations.invite";
try{
const response = UrlFetchApp.fetch(url, options);
const resText = JSON.parse(response).channel;
const chId = resText.id;
if(JSON.parse(response).ok){
return true;
}
return false;
}
catch(e){
return e;
}
今後のTodo
回避策を考える
仮説(検証する)
A案:チャンネルのオーナー情報を書き換えてリネーム
B案:管理者ユーザーの代理でAPI実行する方法
C案:別のAPIを探す(Admin系とか怪しそうなんだよな)