|
| 1 | +--- |
| 2 | +title: Confluence ServerのREST APIを用いたページコピー |
| 3 | +tags: |
| 4 | + - JavaScript |
| 5 | + - jQuery |
| 6 | + - Ajax |
| 7 | + - Confluence |
| 8 | + - REST-API |
| 9 | +private: false |
| 10 | +updated_at: '2020-12-26T17:37:50+09:00' |
| 11 | +id: 0e2871df78aed072291b |
| 12 | +organization_url_name: null |
| 13 | +slide: false |
| 14 | +--- |
| 15 | +#1行概要 |
| 16 | +Confluence Serverの"Get content by id"と"Create content"APIを併用してコピーAPIを実現した。 |
| 17 | + |
| 18 | +#はじめに |
| 19 | +[Confluence](https://www.atlassian.com/ja/software/confluence)(以下、コンフル)はAtlassian社が開発している、いわゆる企業向けウィキシステム。 |
| 20 | +私が4月から勤務している会社でもコンフルを導入しており、主に議事録や週報の作成・共有に使っている。 |
| 21 | + |
| 22 | +ふと週報を作成していて、コピー・命名作業が面倒だったので半自動化したいと思い立った。 |
| 23 | + |
| 24 | +#Confluence Server REST APIについて |
| 25 | +コンフルのAPIはREST形式になっており、パラメータを指定して叩くとJSON形式でデータが返ってくる。 |
| 26 | +利用中のサービスによって**Server REST API**か**Clound REST API**を選択することになるが、弊社の場合は前者になる。 |
| 27 | +なお、後者の方が圧倒的に用意されているAPIメソッドが多い。(コピーAPIも用意されている。) |
| 28 | + |
| 29 | +- [0からREST APIについて調べてみた](https://qiita.com/masato44gm/items/dffb8281536ad321fb08) |
| 30 | +- [Confluence Server REST API Reference](https://docs.atlassian.com/ConfluenceServer/rest/7.3.5/) ←こちらを使用 |
| 31 | +- [Confluence Clound REST API Reference](https://developer.atlassian.com/cloud/confluence/rest/) |
| 32 | + |
| 33 | +#実装 |
| 34 | +###1. 前準備 |
| 35 | +まず、ページのコピーと自動命名を行うスクリプトを格納するページを新規に作成する。 |
| 36 | +コピーをしたいページ、コピーを置きたいページとは異なるので注意。 |
| 37 | +新規ページ作成後「HTML」マクロを埋め込む。 |
| 38 | +<img width="232" alt="html.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/8956f0b8-d050-2bf1-e4f8-e3ee53a85cde.png"> |
| 39 | + |
| 40 | +###2. 処理の記述 |
| 41 | +次のスクリプトを記述する。 |
| 42 | + |
| 43 | +大まかな処理の流れは次の通り。 |
| 44 | +① Ajaxで**[Get content by id](https://docs.atlassian.com/ConfluenceServer/rest/7.3.5/#api/content-getContentById)**APIを叩く |
| 45 | +② コピー元のページBody情報を取得 |
| 46 | +③ Ajaxをネストし**[Create content](https://docs.atlassian.com/ConfluenceServer/rest/7.3.5/#api/content-createContent)**APIを叩く |
| 47 | +④ コピー元のページBodyをコピー先のページBodyに代入 |
| 48 | +⑤ おわり |
| 49 | + |
| 50 | +今回はコピー先のページタイトルに、コピー日の日付(yyyymmdd形式)を指定している |
| 51 | + |
| 52 | +```html |
| 53 | + |
| 54 | +<script type="text/javascript"> |
| 55 | +$(() => { |
| 56 | + $("#btn").click(() => { |
| 57 | + /** |
| 58 | + * コピー元のページID、コピー先のページID、スペースキーの指定 |
| 59 | + */ |
| 60 | + const SRC_PAGE_ID = "【コピー元のページID】"; |
| 61 | + const DST_PAGE_ID = "【コピー先のページID】"; |
| 62 | + const SPACE_KEY = "【スペースキー】"; |
| 63 | +
|
| 64 | + /** |
| 65 | + * ページタイトルの指定 |
| 66 | + */ |
| 67 | + const today = new Date(); |
| 68 | + const pageTitle = |
| 69 | + today.getFullYear() |
| 70 | + + ("0"+ (today.getMonth() +1)).slice(-2) |
| 71 | + + ("0"+ today.getDate()).slice(-2); |
| 72 | +
|
| 73 | + /** |
| 74 | + * 通信用ヘッダー |
| 75 | + */ |
| 76 | + const headers = { |
| 77 | + "Accept": "application/json", |
| 78 | + "content-type": "application/json" |
| 79 | + }; |
| 80 | +
|
| 81 | + /** |
| 82 | + * ①② コピー元の情報取得 |
| 83 | + */ |
| 84 | + $.ajax({ |
| 85 | + type: "get", |
| 86 | + url: "https://【ドメイン名】/rest/api/content/" + SRC_PAGE_ID + "?expand=body.view", |
| 87 | + headers: headers, |
| 88 | + }) |
| 89 | + .done((result) => { |
| 90 | + console.log(result); |
| 91 | + const srcPageBody = result.body.view.value; |
| 92 | + /** |
| 93 | + * ③④ コピー先の作成 |
| 94 | + */ |
| 95 | + $.ajax({ |
| 96 | + type: "post", |
| 97 | + url: "https://【ドメイン名】/rest/api/content", |
| 98 | + headers: headers, |
| 99 | + data: JSON.stringify({ |
| 100 | + "type": "page", |
| 101 | + "ancestors": [{ |
| 102 | + "id": DST_PAGE_ID |
| 103 | + }], |
| 104 | + "title": pageTitle, |
| 105 | + "space": { |
| 106 | + "key": SPACE_KEY |
| 107 | + }, |
| 108 | + "body": { |
| 109 | + "storage": { |
| 110 | + "value": srcPageBody, |
| 111 | + "representation": "storage" |
| 112 | + } |
| 113 | + } |
| 114 | + }), |
| 115 | + success: () => { |
| 116 | + alert("Done"); |
| 117 | + }, |
| 118 | + error: () => { |
| 119 | + alert("Error:コピー先の作成に失敗しました。"); |
| 120 | + } |
| 121 | + }); |
| 122 | + }) |
| 123 | + .fail(() => { |
| 124 | + alert("Error:コピー元の取得に失敗しました"); |
| 125 | + }); |
| 126 | + }) |
| 127 | +}) |
| 128 | +</script> |
| 129 | +<button id="btn">ページコピー</button> |
| 130 | +``` |
| 131 | + |
| 132 | +###3. パラメータの説明 |
| 133 | +- **SRC_PAGE_ID**、**DST_PAGE_ID**:コピー元、コピー先のページID |
| 134 | +- **SPACE_KEY**:各スペースの一意IDで「スペース>スペース ディレクトリ」から確認可能 |
| 135 | + |
| 136 | +>ページIDは、ページURL |
| 137 | +>https://【ドメイン名】/pages/viewpage.action?pageid= |
| 138 | +>の末尾9桁の数字 |
| 139 | +
|
| 140 | +###4. 挙動 |
| 141 | +まずページ上には、`<button id="btn">ページコピー</button>`で記述したボタンが配置されており、ボタンを押下するとスクリプトが動く。 |
| 142 | +コピー元ページの取得とコピー先ページの作成に成功すると、alertメッセージ「Done」と表示される。 |
| 143 | + |
| 144 | + |
| 145 | +ページをリフレッシュすると、元のページツリーから |
| 146 | +<img width="109" alt="copymae.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/e3a907c7-e8fc-e94f-6531-161b6ce35309.png"> |
| 147 | +指定したコピー先に新規ページが作成されている。 |
| 148 | +<img width="117" alt="copyato.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/e1939c2d-bcf8-3019-1c91-cf26549db205.png"> |
| 149 | +ここでは、SRC_PAGE_IDに「テストタイトルです」、DST_PAGE_IDに「02_COPY」というタイトルのペーのIDを指定しており、 |
| 150 | +*DST_PAGE_IDが親で、コピー日の日付をタイトルにした、SRC_PAGE_IDの中身のページ*を作成することができた。 |
| 151 | + |
| 152 | +###5. 確認 |
| 153 | +[Get content by id](https://docs.atlassian.com/ConfluenceServer/rest/7.3.5/#api/content-getContentById)で取得した中身を、`console.log(result)`から開発者メニューで確認することができる。 |
| 154 | + |
| 155 | + |
| 156 | +#おわりに |
| 157 | +Confluence ServerのREST APIを利用したコピーメソッドを実現した。 |
| 158 | +同様に、MoveやCommentといった*Cloud APIにはあって、Server APIにはないメソッド*がまだ多数ある。それらも実現できたらいいね(遠い目)。 |
0 commit comments