Confluence APIでページを作成・編集・削除・検索する

## API Document

- https://developer.atlassian.com/cloud/confluence/rest/v2/intro <- 基本はこちらのv2を使う
- [atlassian-python-api doc](https://atlassian-python-api.readthedocs.io/confluence.html) <- 2024/11 時点でまだv1が使われている
    - [confluence.py](https://github.com/atlassian-api/atlassian-python-api/blob/master/atlassian/confluence.py) ([github](https://github.com/atlassian-api/atlassian-python-api))

## Prerequisite

### Token

https://id.atlassian.com/manage-profile/security/api-tokens から取得

### Env

```
ATLASSIAN_CONFLUENCE_URL=https://xxxx.atlassian.net/wiki/
ATLASSIAN_USERNAME=<youremail>
ATLASSIAN_API_TOKEN=<token>
CONFLUENCE_ACCESS_EMAIL_AND_TOKEN="${ATLASSIAN_USERNAME}:${ATLASSIAN_API_TOKEN}"
CONFLUENCE_SPACE_KEY=<your space key>
```

## Getting Started

### Get content (v1)

```
curl -X GET "${ATLASSIAN_CONFLUENCE_URL}/rest/api/content?spaceKey=$CONFLUENCE_SPACE_KEY" \
  -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json'
```

### Get Content by ID (v1)

```
PAGE_ID=xxx
curl -X GET "${ATLASSIAN_CONFLUENCE_URL}/rest/api/content/${PAGE_ID}?expand=body.storage" \
  -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json'
```

### Get Page Views (v1)

```
CONTENT_ID=xxx
curl -X GET "${ATLASSIAN_CONFLUENCE_URL}/wiki/rest/api/analytics/content/$CONTENT_ID/views" \
  -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json'
```

### Get Page Viewers (v1)

```
curl -X GET "${ATLASSIAN_CONFLUENCE_URL}/wiki/rest/api/analytics/content/$CONTENT_ID/viewers" \
  -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json'
```

### Get [Page with likes](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/#api-pages-id-get) (v2)

```
curl -X GET "${ATLASSIAN_CONFLUENCE_URL}/wiki/api/v2/pages/$CONTENT_ID?include-likes=true" \
  -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json'
```

### Create a page with parent page

```
PARENT_PAGE_ID=xxx
curl -X POST "${ATLASSIAN_CONFLUENCE_URL}/rest/api/content" \
  -u  $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "API POST TEST",
  "type": "page",
  "space": {
    "key": "${CONFLUENCE_SPACE_KEY}"
  },
  "status": "current",
  "ancestors": [
    {
      "id": "${PARENT_PAGE_ID}"
    }
  ],
  "body": {
    "storage": {
      "value": "<h3>test</h3><br/>test post from api",
      "representation": "storage"
    }
  }
}'
```

### Update a page (v1)

https://developer.atlassian.com/server/confluence/confluence-rest-api-examples/#update-a-page <- こちら

### Delete a page (v1)

```
curl -v -S -u $CONFLUENCE_ACCESS_EMAIL_AND_TOKEN -X DELETE ${ATLASSIAN_CONFLUENCE_URL}/rest/api/content/<content_id>
```

### Copy a page (v2)

1. Get page by id: https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/#api-pages-id-get

1. Create page: https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/#api-pages-post

:::note info
spaceIdは、数字。 space keyではないので注意
:::


Pythonの例:

```py
import requests
import json
import os
# ConfluenceのベースURLとAPIエンドポイント
base_url = os.environ["ATLASSIAN_CONFLUENCE_URL"]
# Confluenceの認証情報
user_name, api_token = os.environ["ATLASSIAN_USERNAME"], os.environ["ATLASSIAN_API_TOKEN"]
source_page_id = '<source_page_id>'
destination_parent_page_id = '<parent_page_id>'
# This code sample uses the 'requests' library:
# http://docs.python-requests.org
import requests
from requests.auth import HTTPBasicAuth
import json
url = f"{base_url}/api/v2/pages/{source_page_id}?body-format=storage"
auth = HTTPBasicAuth(username=user_name, password=api_token)
headers = {
  "Accept": "application/json"
}
response = requests.request(
   "GET",
   url,
   headers=headers,
   auth=auth
)
source_page = response.json()
print(source_page)
# 新しいページのデータを作成する
new_page_data = {
    "spaceId": source_page["spaceId"],
    "title": f"Copy of {source_page['title']}",
    "parentId": source_page['parentId'],
    "body": {
        "value": source_page['body']['storage']['value'],
        "representation": "storage"
    }
}
# 新しいページを作成する
headers = {
    'Content-Type': 'application/json'
}
response = requests.post(f"{base_url}/api/v2/pages", headers=headers, auth=auth, data=json.dumps(new_page_data))
if response.status_code == 200 or response.status_code == 201:
    print("ページが正常にコピーされました。")
else:
    print(f"エラーが発生しました: {response.status_code}")
    print(response.text)
```

:::note warn
API経由で作成するとなぜか old editorになる
https://jira.atlassian.com/browse/CONFCLOUD-68057?focusedId=3316099&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-3316099

https://community.developer.atlassian.com/t/confluence-rest-api-v2-struggling-to-create-a-page-with-the-new-editor/75235/5 <- propertyをUpdateしてあげればいい。
propertyの取得方法と更新方法は次のセクションを参考に
:::


# [Get a specific Property](https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-content-properties/#api-pages-page-id-properties-get) (例. editor)

以下の例では、`editor` プロパティを取得する

```py
import os
import requests
from requests.auth import HTTPBasicAuth
import json

base_url = os.environ["ATLASSIAN_CONFLUENCE_URL"]
page_id = <page_id>
property = "editor"
property_editor_url = f"{base_url}/api/v2/pages/{page_id}/properties?key={property}"
auth = HTTPBasicAuth(os.environ["ATLASSIAN_USERNAME"], os.environ["ATLASSIAN_API_TOKEN"])

headers = {
  "Accept": "application/json"
}

response = requests.request(
   "GET",
   property_editor_url,
   headers=headers,
   auth=auth
)
```

## Update a property (例. editor)

以下の例では`editor` propertyを `v2`に変更する

```py
import os
import requests
from requests.auth import HTTPBasicAuth
import json

page_id = <page_id>
base_url = os.environ["ATLASSIAN_CONFLUENCE_URL"]
response = requests.post(
    f"{base_url}/api/v2/pages/{page_id}/properties",
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json"
    },
    auth=auth,
    data=json.dumps({
        "key": "editor",
        "value": "v2"
    })
)
```

## Search by CQL

- https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/
- https://atlassian-python-api.readthedocs.io/confluence.html#cql

```py
url = os.environ["CONFLUENCE_URL"]
username = os.environ["ATLASSIAN_USERNAME"]
password = os.environ["ATLASSIAN_PASSWORD"]
client = ConfluenceClient(url, username, password)
print(client.search_by_cql("space = SPACEKEY AND text ~ 'git'"))
```

### ConfluenceのUI検索と同じCQL

```
siteSearch ~ 'keyword'
```
Ref

https://stackoverflow.com/questions/78617576/in-confluence-how-to-replicate-manual-search-with-api-search