概要
SlackからTodoistにタスクを追加するbotは公式の提供するものが存在する。
本記事では公式の提供する機能の一つと、Scrapboxでページを作成するオプションを持つbotを実装した。実装した機能を以下に示す。
オプション | 詳細 |
---|---|
. or タスク | タスクの追加を行う |
#(プロジェクト名) | プロジェクトの下に追加する 未指定ならinbox |
!(優先度) | 優先度を「(弱)1-4(強)」で設定する 未指定なら1 |
@(期限) | 期限を設定する |
-s | Scrapboxに同名ページを作成する |
下準備
本記事で説明するコードは事前に以下の準備が必要である。本記事での説明は省略する。
- Incoming WebHooksの設定
- Outgoing Webhooksの設定
- Todoist tokenの取得
- Todoistの[設定]>[連携機能]>[APIトークン]
- GoogleAppsScriptをWebアプリケーションとして導入
実装
「Scrapboxのページを作成する」はScrapboxのリンクを作成することで実現している。そのページが存在しない場合は新規作成されるが、存在する場合はページへのリンクとなる。(参考)
コードを以下に示す。
makeTask.gs
function doPost(e) {
//Incoming WebHooksの設定で入手したWebHookURL
var postUrl="https://hooks.slack.com/services/*******";
var userMessage = (e.parameter.text).replace("タスク","");
userMessage = (userMessage).replace(".","");
var status = createTask(userMessage);
var answerText,answerUrl;
// botの表示名などを変更する。WebHook設定の方が優先されることもあるため気になる場合は確認する、
var jsonData = {
"channel" : "#reminder",
"username" : "Todoist連携さん",
"icon_emoji" :":ghost:",
};
if (status[0] === 200) {
answerText = "Todoistにタスクを追加しました。";
if(status[1]){
answerText += "Scrapboxにページを作成します。";
answerUrl = createPage(status[2]);
jsonData["attachments"] = [{
"fallback": answerText+"("+answerUrl+")",
"color": "#36a64f",
"pretext": answerText,
"title": "Scrapbox-"+status[2],
"title_link": answerUrl,
}];
}else{
jsonData["text"]=answerText;
}
} else {
answerText = "Todoistへのタスク追加に失敗しました。";
jsonData["text"]=answerText;
}
var options =
{
"method" : "post",
"contentType" : "application/json",
"payload" : JSON.stringify(jsonData)
};
UrlFetchApp.fetch(postUrl, options);
}
function createTask(userMessage) {
var url = "https://todoist.com/API/v7/sync",
todoistToken = "*******************************",
uuid = Utilities.getUuid(),
tempId = Utilities.getUuid(),
task = strToTask(userMessage),
projectId = searchProject(task['projectName'],todoistToken),
formData, response;
formData = {
"token": todoistToken,
"commands": JSON.stringify([{
"type": "item_add",
"temp_id": tempId,
"uuid": uuid,
"args": {
"priority" : task['priority'],
"content": task['taskName'],
"project_id": projectId,
"due": {
"string": task['limit'],
},
}
}])
};
response = UrlFetchApp.fetch(url, {
"method" : "post",
"payload" : formData
});
return [response.getResponseCode(),task['scrapbox'],task['taskName']];
}
function createPage(taskName){
// Scrapboxのページを作成する
// ******部分にはScrapboxのプロジェクト名を入力しておく
var url = "https:///scrapbox.io/*******/"+taskName+"";
url=encodeURI(url);
Logger.log(url);
return url;
}
function strToTask(str){
var response = {};
// !優先度 で設定
var priority = str.match(/([!!][1-41-4])/);
if(priority){
str = str.replace(priority[0],"");
response['priority'] = priority[0].slice(1);
} else {
response['priority'] = 1;
}
// -s でScrapboxのページを作成
var scrapboxOption = str.match(/(-s)/);
if(scrapboxOption){
str = str.replace(scrapboxOption[0],"");
response['scrapbox'] = true;
} else {
response['scrapbox'] = false;
}
// #既存のプロジェクト で設定
var projectName = str.match(/(#|#)[^(@|@)]*/);
if(projectName){
str = str.replace(projectName[0],"");
response['projectName'] = projectName[0].slice(1);
}
// @期限 で設定
var limit = str.match(/(@|@).*/);
if(limit){
str = str.replace(limit[0],"");
response['limit'] = limit[0].slice(1);
}
response['taskName'] = str;
return response;
}
function searchProject(projectName,token){
var url = "https://todoist.com/API/v7/sync",
formData,options,response;
var headers = {
"Accept": "application/json",
};
formData ={
"token": token,
"sync_token":"*",
"resource_types":'["projects"]',
};
response = UrlFetchApp.fetch(url,{
"contentType": "application/json",
"headers":headers,
"method":"post",
"payload":JSON.stringify(formData)
});
var array = JSON.parse(response.getContentText());
for(var i = 0; i < array["projects"].length; i++){
if(array["projects"][i]["name"]===projectName){
return array["projects"][i]["id"];
}
}
return 000000;
}
実行結果
実際に利用しているbotは上記コードからアイコンとコメントを変更したものである。
Todoist上では以下のように表示される。