Skip to content

Commit f6fcf66

Browse files
committed
support markdown and attachments
1 parent a999726 commit f6fcf66

2 files changed

Lines changed: 39 additions & 9 deletions

File tree

pyconfluence/actions.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,21 @@ def create_page(name, parent_id, space, content):
243243
data["body"] = {"storage": {"value": content, "representation": "storage"}}
244244
return _api.rest("/", "POST", _json.dumps(data))
245245

246+
def attach_file(name, id, content, comment=None):
247+
"""Create attachment in Confluence.
248+
Parameters:
249+
- name of the attachment
250+
- id: ID of the page to attach to
251+
- content: conent of the attachment as io.BytesIO
252+
- comment: comment for attachment (optional)
253+
"""
254+
data = {
255+
"comment" : name if comment == None else comment
256+
}
257+
files = {
258+
'file' : (name, content)
259+
}
260+
return _api.rest(f"/{id}/child/attachment", "POST", data, files)
246261

247262
def edit_page(id, name, space, content):
248263
"""Update a page in Confluence.
@@ -292,3 +307,14 @@ def delete_page_full(id):
292307
delete_page_full(i["id"])
293308

294309
return delete_page(id)
310+
311+
def markdown2xhtml(content):
312+
"""Convert Markdown to xhtml
313+
Parameters:
314+
- content: the contnent to covert
315+
"""
316+
data = {
317+
"value" : content,
318+
"representation":"wiki",
319+
}
320+
return _api.rest("/../contentbody/convert/storage", "POST", _json.dumps(data))

pyconfluence/api.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,36 +35,37 @@ def load_variables():
3535
base_url = ("https://" + os.environ["PYCONFLUENCE_ORG"] + ".atlassian"
3636
".net/wiki/rest/api/content")
3737

38-
39-
def rest(url, req="GET", data=None):
38+
def rest(url, req="GET", data=None, files=None):
4039
"""Main function to be called from this module.
4140
4241
send a request using method 'req' and to the url. the _rest() function
4342
will add the base_url to this, so 'url' should be something like '/ips'.
4443
"""
4544
load_variables()
4645

47-
return _rest(base_url + url, req, data)
46+
return _rest(base_url + url, req, data, files)
4847

4948

50-
def _rest(url, req, data=None):
49+
def _rest(url, req, data=None, files=None):
5150
"""Send a rest rest request to the server."""
52-
if url.upper().startswith("HTTPS"):
51+
if not url.upper().startswith("HTTPS"):
5352
print("Secure connection required: Please use HTTPS or https")
5453
return ""
54+
if "../" in url:
55+
url = url.replace("https://","")
56+
url = "https://" + os.path.normpath(url)
5557

5658
req = req.upper()
5759
if req != "GET" and req != "PUT" and req != "POST" and req != "DELETE":
5860
return ""
5961

60-
status, body = _api_action(url, req, data)
62+
status, body = _api_action(url, req, data, files)
6163
if (int(status) >= 200 and int(status) <= 226):
6264
return body
6365
else:
6466
return body
6567

66-
67-
def _api_action(url, req, data=None):
68+
def _api_action(url, req, data=None, files=None):
6869
"""Take action based on what kind of request is needed."""
6970
requisite_headers = {'Accept': 'application/json',
7071
'Content-Type': 'application/json'}
@@ -76,8 +77,11 @@ def _api_action(url, req, data=None):
7677
response = requests.put(url, headers=requisite_headers, auth=auth,
7778
data=data)
7879
elif req == "POST":
80+
if files != None:
81+
requisite_headers.pop('Content-Type',None)
82+
requisite_headers["X-Atlassian-Token"] = "no-check"
7983
response = requests.post(url, headers=requisite_headers, auth=auth,
80-
data=data)
84+
data=data, files=files)
8185
elif req == "DELETE":
8286
response = requests.delete(url, headers=requisite_headers, auth=auth)
8387

0 commit comments

Comments
 (0)