私は,QiitaのクローンであるOSS、Knowledge(以下URL参考)を社内運用している。
https://information-knowledge.support-project.org/ja/
Knowledgeには記事投稿やコメントをTriggerとしてWebhookを投げる機能が備わっているが、KnowledgeのJSONフォーマットがSlackのIncomingWebhookで受け付けるJSONフォーマットと一致していないため、Slackへ変更通知を出すには変換をする中継地点が必要である。
本記事では、GoogleAppsScript(GAS)を中継地点として利用して、Knowledge更新通知をSlackに投稿する方法を紹介する。
Knowledgeの設定
Webhookの設定をするだけ.
宛先URLはGASをWebアプリとして公開しているURL
Slackの設定
IncomingWebhookで,通知受取用のエンドポイントURLを設定しておく.
このURLをGASから叩く
GAS
以下の点を考慮してスクリプトをコーディングした
- SlackのIncomingWebhookのURLはスクリプトプロパティに格納した
- →Qiitaにコードをコピペする際に、気にする必要がなくて楽だった
- 非公開の記事については通知を出したくない
- →public_flag=2(公開範囲保護設定)の記事のみを対象とした.
- コメントや記事の内容は知りたいけど,長いポストはしたくない
- →最初の100文字だけSlack通知に含めるようにした.
- せっかくなので,Attachmentsで少し目立つ通知になるように工夫したい.
- →コメント・新規投稿・過去投稿の更新,の3つで色分け
- ついでに,スプレッドシートに投稿記録を貯めたい.
- →誰が,どのくらい投稿しているか,等を見える化出来たら良いなと考え中...
doPost
KnowledgeのWebhookを受け取って実行される関数
function doPost (e) {
// << PostData の処理 >>
var org_post = e.postData.contents;
var contents = JSON.parse(org_post);
var knowledge = contents;
var sheet = sheet_knowledge;
// << 分岐 >>
// <1.comment>
if (contents.hasOwnProperty("comment")){
var sheet = sheet_comment;
recordComment(contents)
// 保護:Slack通知
if (contents.knowledge.public_flag == 2){
var type = "[Posted new comment]"; //通知の種類
var knowledge = contents.knowledge;
var comment = contents.comment; //コメント
var user = contents.insert_user; //投稿者
var date = contents.insert_date; //日時
// 非公開の記事へのコメント:Slack通知しない
} else {
checkSuccess(sheet,"Not notified")
return;
}
// <2.knowledge-update>
}else if(knowledge.public_flag == 2 && knowledge.status == "updated"){
//}else if(knowledge.status == "updated"){ // Test用
recordKnowledge(contents)
var type = "[Updated knowledge]" //通知の種類
var user = knowledge.update_user; //投稿者
var date = knowledge.update_date; //日時
// <3.knowledge-created>
}else if(knowledge.public_flag == 2 && knowledge.status == "created"){
//}else if(knowledge.status == "created"){ // Test用
recordKnowledge(contents)
var type = "[Created new knowledge]"; //通知の種類
var user = knowledge.insert_user; //投稿者
var date = knowledge.insert_date; //日時
// <4.others>
}else{
recordKnowledge(contents)
checkSuccess(sheet,"Not notified")
return;
}
var content = knowledge.content; // Knowledgeの本文
var title = knowledge.title; // Knowledgeのタイトル
var link = knowledge.link; // Knowledgeへのリンク
// << POST data の準備 >>
var attachments = [
{
"callback_id": "knowledge",
"fallback": "Notification from Knowledge",
"attachment_type": "default",
"title": title,//インデント内に表示されるタイトル
"title_link": link,
"color":"good",
"fields": [
{
"title": "Date",
"value": date,
"short": "true"
},
{
"title": "User",
"value": user,
"short": "true"
}
]
}
]
// Comment/Content追加
if (contents.hasOwnProperty("comment")) {
attachments[0].fields[3] = {
"title": "Comment",
"value": comment.slice(0,100).replace(/\r\n|\r|\n/g, '\n')+" ................."
}
attachments[0].color = "warning";
} else {
attachments[0].fields[3] = {
"title": "Knowledge",
// 100文字に限定
"value": content.slice(0,100).replace(/\r\n|\r|\n/g, '\n')+" ................."
}
if (knowledge.status == "updated") {
attachments[0].color = "bad";
}
}
// << Slack >>
var payload = {
"attachments": attachments,
"text": type
}
// URL
var properties = PropertiesService.getScriptProperties();
var url = properties.getProperty("url_knowledge"); // 本番用:#knowledge
//var url = properties.getProperty("url_test"); // Test用:#knowledge_test
var option = {
"method": "POST",
"payload": JSON.stringify(payload),
"contentType": "application/json"
}
// Slack Incoming WebhookへPost
UrlFetchApp.fetch(url, option)
// Spreadsheetに保存
checkSuccess(sheet,"Success")
}