]> BookStack Code Mirror - api-scripts/blob - python-upload-attachment/main.py
Update README.md
[api-scripts] / python-upload-attachment / main.py
1 import os
2 import sys
3 import requests
4
5 # This is where BookStack API details can be hard-coded if you prefer
6 # to write them in this script instead of using environment variables.
7 default_bookstack_options = {
8     "url": "",
9     "token_id": "",
10     "token_secret": "",
11 }
12
13
14 # Gather the BookStack API options either from the hard-coded details above otherwise
15 # it defaults back to environment variables.
16 def gather_api_options() -> dict:
17     return {
18         "url": default_bookstack_options["url"] or os.getenv("BS_URL"),
19         "token_id": default_bookstack_options["token_id"] or os.getenv("BS_TOKEN_ID"),
20         "token_secret": default_bookstack_options["token_secret"] or os.getenv("BS_TOKEN_SECRET"),
21     }
22
23
24 # Send a multipart post request to BookStack, at the given endpoint with the given data.
25 def bookstack_post_multipart(endpoint: str, data: dict) -> dict:
26     # Fetch the API-specific options
27     bs_api_opts = gather_api_options()
28
29     # Format the request URL and the authorization header, so we can access the API
30     request_url = bs_api_opts["url"].rstrip("/") + "/api/" + endpoint.lstrip("/")
31     request_headers = {
32         "Authorization": "Token {}:{}".format(bs_api_opts["token_id"], bs_api_opts["token_secret"])
33     }
34
35     # Make the request to bookstack with the gathered details
36     response = requests.post(request_url, headers=request_headers, files=data)
37
38     # Throw an error if the request was not successful
39     response.raise_for_status()
40
41     # Return the response data decoded from it's JSON format
42     return response.json()
43
44
45 # Error out and exit the app
46 def error_out(message: str):
47     print(message)
48     exit(1)
49
50
51 # Run this when called on command line
52 if __name__ == '__main__':
53
54     # Check arguments provided
55     if len(sys.argv) < 3:
56         error_out("Both <page_id> and <file_path> arguments need to be provided")
57
58     # Gather details from the command line arguments and create a file name
59     # from the file path
60     page_id = sys.argv[1]
61     file_path = sys.argv[2]
62     file_name = os.path.basename(file_path)
63
64     # Ensure the file exists
65     if not os.path.isfile(file_path):
66         error_out("Could not find provided file: {}".format(file_path))
67
68     # Gather the data we'll be sending to BookStack.
69     # The format matches that what the "requests" library expects
70     # to be provided for its "files" parameter.
71     post_data = {
72         "file": open(file_path, "rb"),
73         "name": (None, file_name),
74         "uploaded_to": (None, page_id)
75     }
76
77     # Send the upload request and get back the attachment data
78     try:
79         attachment = bookstack_post_multipart("/attachments", post_data)
80     except requests.HTTPError as e:
81         error_out("Upload failed with status {} and data: {}".format(e.response.status_code, e.response.text))
82
83     # Output the results
84     print("File successfully uploaded to page {}.".format(page_id))
85     print(" - Attachment ID: {}".format(attachment['id']))
86     print(" - Attachment Name: {}".format(attachment['name']))