Slackのコメントにリアクションをつけたらasanaのタスクを作成してほしい②
こんばんは、tmdです。
はい、同じタイトルですね、完成したと、思ったんですよね。
完成したつもりだったのですが、とある要望を受けましたので②です。
前回の記事
もらった要望に関する説明
チャンネル増えるたびにbotを招待することが手間である
代わりに完了のリアクションはなくなってもよい
とのことなのでこんな感じで新旧の変更がありました。
表にするとこんな感じ
図で比較するとこんな感じ。
下準備
スプシ
前回作ったものをそのまま流用しますが、タスクスケジューラ用に1つシートの追加が必要です。
ひとまず「設定」というシートがあり、セルのB1に前回に取得したコメントの日時、C1に前回取得したURL、D1に前回のタイムスタンプが入るていで進めます。
Slackのbot
前回用意したものがほとんどそのまま流用できます、不要なものはEventSubscriptions、reactions:readとreactions:writeも不要なはず。
ReacjiChanneler
コメントを送信するSlackチャンネルを用意してください。
ReacjiChannelerでスプレッドシートで設定した絵文字と同じものが反応するように設定してください
ReacjiChannelerの設定等についてはこちらを参考にしてください。
コードについて
上記の説明で感づいているかもしれませんが、
このコードはつまり、「特定のチャンネルにある投稿がに付随するiconがスプレッドシートと一致している場合はAsanaのタスクを作る」という挙動になります。
前回との記載方法もちょっと違いがあります。
トークンなどは
プロジェクトの設定>スクリプト プロパティ に登録しました。
スクリプトプロパティに入れたものは以下のようにすると設定した値が取得できるみたいです。
PropertiesService.getScriptProperties().getProperty('プロパティ名')
冒頭部分
スクリプトプロパティの値とスプレッドシートについてはグローバル変数として定義しています。
const SlackToken= PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN')
const AsanaToken= PropertiesService.getScriptProperties().getProperty('ASANA_ACCESS_TOKEN')
const workspaceId= PropertiesService.getScriptProperties().getProperty('ASANA_WORKSPACE_ID')
const projectId= PropertiesService.getScriptProperties().getProperty('ASANA_PROJECT_ID')
const channelID= PropertiesService.getScriptProperties().getProperty('SLACK_CHANNEL_ID')
var ss = SpreadsheetApp.getActiveSpreadsheet();
function setSlackLog(){
var sheetUpdateTime= ss.getSheetByName("設定");
var dataUpdateTime = sheetUpdateTime.getRange("B1").getValue();
var keep_url = sheetUpdateTime.getRange("C1").getValue();
var keep_ts = sheetUpdateTime.getRange("D1").getValue();
var response = JSON.parse(getSlackLog(dataUpdateTime));
var messages = response.messages.reverse();
var asanaUserGid;
for (var i = 0; i < messages.length; i++ ){
var icons = messages[i].icons;
var ts = messages[i].ts;
var attachments = messages[i].attachments;
if (icons){
var emoji = icons.emoji;
asanaUserGid = reactionList(emoji);
if (asanaUserGid>0){
if(attachments){
var from_url = attachments[0].from_url;
var fallback = attachments[0].text;
var channel = attachments[0].channel_id;
var attachmentsts=attachments[0].ts;
if(keep_url!=attachments[0].from_url && ts>keep_ts){
asanaTaskCreate2(from_url,fallback,asanaUserGid);
sheetUpdateTime.getRange("B1").setValue(convertTimestamp(messages[i].ts));
sheetUpdateTime.getRange("C1").setValue(attachments[0].from_url);
sheetUpdateTime.getRange("D1").setValue(ts);
};
};
};
};
};
};
Slackから値を取得する部分
function getSlackLog(dataUpdateTime) {
var requestUrl = 'https://slack.com/api/conversations.history?';
var payload = {
'channel': channelID,
'oldest': parseInt( dataUpdateTime / 1000 )
};
var headers = {
'Authorization': 'Bearer '+SlackToken
};
var options = {
'headers': headers
};
var param = [];
for (var key in payload) {
param.push(key + '=' + payload[key]);
}
requestUrl += param.join('&');
return UrlFetchApp.fetch(requestUrl,options);
};
スプシに書き込むときの日付の変換している部分
function convertTimestamp(timestamp) {
var date_format = function(num) {
return ( num < 10 ) ? '0' + num : num;
};
var d = new Date(timestamp * 1000);
var date = d.getFullYear() + '/';
date += date_format( d.getMonth() + 1 ) + '/';
date += date_format( d.getDate() ) + ' ';
date += date_format( d.getHours() ) + ':' + date_format( d.getMinutes() );
return date;
}
絵文字が一致するか確認している部分
function reactionList(reaction){
var sheetName = ss.getSheetByName('スプシの絵文字一覧');
const range = sheetName.getRange(2, 1, sheetName.getLastRow() - 1,3).getValues();
var return1 = 0;
for (i=0;i<sheetName.getLastRow()-1;i++){
if (range[i][0].indexOf(reaction) >= 0){
return range[i][2];
};
};
return 0;
};
Asanaに書き込む部分
■参考にした記事
AsanaのAPIに関しては私が書いたほかのnote記事同様にこちらの記事が参考になりました。ありがとうございました。
function asanaTaskCreate2(from_url,fallback,usetGidId){
var today = new Date();
var todayStr = Utilities.formatDate(today, 'JST', 'yyyy-MM-dd');
var todayStr2 = Utilities.formatDate(today, 'JST', 'yyyy-MM-dd H:MM:SS');
const name = "[Slack作成]"+todayStr2;
const planText = fallback+"\n"+from_url
const userId = usetGidId; //IDで指定
const objTask = {
"data": {
"workspace": workspaceId,
"projects": [projectId],
"name": name,
"notes": planText,
"assignee": { "gid": userId, "resource_type": "user" },
"due_on": todayStr
}
};
//オブジェクトを作成する
const asanaManager = new AsanaManager(AsanaToken);
//処理を呼ぶ
asanaManager.createTask(objTask)
}
class AsanaManager {
constructor(token) {
this.token = token;
}
//タスクの作成
createTask(objPayload) {
const url = `https://app.asana.com/api/1.0/tasks`;
const data = this.postAsanaData(url, objPayload);
console.log('createTask', data);
return data;
}
//postでAsanaからデータ追加する関数
postAsanaData(url, objPayload) {
const token = this.token;
const options = this.getPostOption(token, objPayload);
const response = UrlFetchApp.fetch(url, options);
const jobj = JSON.parse(response);
if (response.getResponseCode() !== 201) {
console.log(jobj);
}
const data = jobj["data"];
return data;
}
//postバージョンのオプションを返す
getPostOption(token, objPayload) {
const headers = {
"Authorization": "Bearer " + token
};
const payload = this.getJson(objPayload);
const options = {
"method": "post",
"contentType": "application/json",
"Accept": "application/json",
"headers": headers,
"payload": payload,
"muteHttpExceptions": true,
"number_value":"test"
}
return options;
}
//オブジェクトをJSONにする
getJson(object) {
var json = JSON.stringify(object);
console.log(json);
return json;
}
}
さいごに
こちらのコードを「トリガー」の画面で任意の時間おきに稼働するようにすれば、リアクションが押されたコメントはAsanaのタスクが作成されえる仕組みです。
それではまた会う日まで。