はじめに
「Confluence」はAtlassianが提供する共有ワークスペース。
現在、社内の情報共有の場として、使用していますが、
アドインや提携しているサービスが豊富で、自由度は**無限大!!**のように感じます。
Confluenceのページ定期更新にいたる背景
とある先輩社員Nさんのつぶやきから、始まりました…。
Nさん:「コンフルのページにイベントまで○○日みたいなカウントダウンのやつ欲しいんだけどー」
私:「イイネ!!やってみよう!(htmlマクロあるっぽいし、Javascriptでおけでしょ)」
--- 問題発生 ---
- 社内で使用しているクラウド版コンフルでは、「htmlマクロ」が使えない?
- クラウド版でも代替のアドインがあった!だが…私はコンフルの管理者権限を持っていないので、勝手に追加はできない…。(しかも、
こんなことのために管理者様の手を煩わせるわけにはいかない…)
--- かすかな希望 ---
- コンフルにはAPI(GET,POST,PUT,DELETE)が存在する。
- 個人単位でAPIキーが発行できる。(管理者様の手を煩わせず、1人で完結できる!)
- 1日毎に定期更新すれば、あたかも毎日勝手にカウントダウンしているように見せれる!?
Nさん:「無理そうならいいやー、ちょっと言ってみただけー」
(無理なことなんてない、かすかな希望があるんです)
APIをたたくスクリプトを用意して、1日おきに定期実行で該当箇所更新させたる!
て、ことで、長くなりましたが、
Google Apps Script(以下GAS)で、コンフルAPIをたたいて、ページを更新させたいとなりました。
加えて、定期実行も!(GASをチョイスしたのは、定期実行が簡単に設定できるからです。※1)
※1 後述しますが、毎日の定期実行が簡単に設定できるのは、1時間単位。
なので、0時ぴったりなど、クリティカルな時間調整が必要な場合には向いていません。
やってみよう
ConfluenceRESTAPIドキュメント:https://developer.atlassian.com/cloud/confluence/rest/
1.APIキーの取得
まずは、ATTLASSIANアカウント管理ページに遷移し、「APIトークンを作成する」をクリック。
作成後、2度と見れないからなとかなり脅されるので、黙ってコピーして、保管する。
2. GASにスクリプトを記述
○ソースコード1
以下の3点を認証ヘッダに付与してAPIリクエストを行うので、定義&ヘッダ作成関数を用意する。
- APIの対象となるワークスペース
- アクセスに使用するユーザー
- APIキー
// API情報を定義
// APIで表示及び更新したいコンフルのワークスペース
var API_BASE_URL = 'https://xxxxxxxxx/wiki';
var user_id = 'メールアドレス';
var password = '1.で取得したAPIキー';
// 更新対象のページIDを定義
var page_id = '111111111';
/* 認証ヘッダー作成関数 */
function create_headers(user_id, password) {
return {
'content-type' : 'application/json',
'Authorization' : 'Basic ' + Utilities.base64Encode(user_id + ':' + password)
};
}
○ソースコード2
GET時のパラメータであるexpandはGET時に何を取得するかをカンマ区切りで指定する。
キー | 取得するもの |
---|---|
space | 取得対象のページが所属するスペース |
version | 取得対象のページのバージョン |
history | 取得対象のページの履歴 |
body | 取得対象のページ本文 |
/* コンフルのGETAPI呼び出し関数 */
function get_previous_content(headers, page_id, expand_string) {
var options = {
'headers' : headers,
'method' : 'get'
};
// 記事内容を取得
var api_url = API_BASE_URL + '/rest/api/content/' + page_id + '?expand=' + expand_string;
var response = UrlFetchApp.fetch(api_url, options).getContentText('UTF-8');
var content_json = JSON.parse(response);
return content_json;
}
/* コンフルのPUTAPI呼び出し関数 */
function put_content(headers, page_id, current_version, new_page_title, new_page_body, expand_string) {
var new_version = current_version + 1; // バージョンを更新
// 更新内容を定義
var payload = {
'type' : 'page',
'version' : {'number' : new_version},
'title' : new_page_title,
'body' : {
'storage' : {
'value' : new_page_body,
'representation' : 'storage'
}
}
};
payload = JSON.stringify(payload);
options = {
'headers' : headers,
'payload' : payload,
'method' : 'put'
};
// 記事内容を更新
var api_url = API_BASE_URL + '/rest/api/content/' + page_id;
var response = UrlFetchApp.fetch(api_url, options).getContentText('UTF-8');
var content_json = JSON.parse(response);
return content_json;
}
○ソースコード3
Mainとなる関数。
現在の記事内容を取得して、
**<strong>~日</strong>**の部分を1日減算して、ページを更新する処理を定義する。
正規表現の部分を変更すれば、どんな箇所でも更新可能です。
/* 記事を更新する関数 */
function updateContent() {
// 現在の記事内容を取得
var headers = create_headers(user_id, password);
var prev_content = get_previous_content(headers, page_id, 'body.storage,version');
// 記事内容を変更
var pattern_match = prev_content.body.storage.value.match(/<strong>([\s\S]*?)日<\/strong>/);
// 数値部分を抜粋
var day = parseInt(pattern_match[0].replace(/[^0-9^\.]/g, ""), 10);
// 0よりも大きければ、日数を減算
if (day > 0) {
day -= 1;
// 更新後コンテンツを定義
var new_page_content = prev_content.body.storage.value.replace(/<strong>([\s\S]*?)日<\/strong>/, "<strong>" + day + "日</strong>");
// 更新
var content_json = put_content(headers, page_id, prev_content.version.number, prev_content.title, new_page_content, null);
}
}
3. スクリプトを実行
意図したページになっているかを確認。
4. GASを定期実行する。
今回の詳細は、
updateContent関数を1日に1回午前0時~1時の間に実行する。
「午前0時~1時の間に」→この部分が前述したGASがクリティカルな時間調整が必要な場合には向いていない理由
何分に実行するかどうかまでは、指定できません。
これで、定期実行設定完了!
あとは、明日の実行結果を待つのみ。
まとめ
- コンフルに管理者権限等がなくてもAPIキーは発行できるので、個人ベースでAPIを使用できる。
- GASの記法はほぼJavascriptなので、学習コストが抑えられる。
- GASでhtmlを扱うのは少々困難。(私が正規表現苦手なだけ…??何度もデバックして確認しました…。)
- GASなら定期実行も簡単にできる。
- 間違っても、定期実行で1分おきとかにしないように!!(通知を受けている人がいると、えらいことに…。)