|
1 | 1 | import requests
|
2 | 2 | import json
|
| 3 | +import time |
| 4 | +import datetime |
| 5 | +from datetime import timezone |
| 6 | +import mimetypes |
3 | 7 |
|
4 | 8 | from pikepdf import Pdf
|
5 | 9 |
|
|
16 | 20 | }
|
17 | 21 |
|
18 | 22 | class Onedoc:
|
19 |
| - def __init__(self, api_key: str, endpoint: str = "https://app.onedoclabs.com"): |
| 23 | + def __init__(self, api_key: str, endpoint: str = "https://api.fileforge.com"): |
20 | 24 | self.api_key = api_key
|
21 | 25 | self.endpoint = endpoint
|
22 | 26 |
|
23 | 27 | def _build_url(self, path: str) -> str:
|
24 | 28 | return f"{self.endpoint}{path}"
|
25 | 29 |
|
26 |
| - def _upload_to_signed_url(self, url_to_fs: str, path: str, file_body: Any, file_options: Dict = None) -> Dict: |
27 |
| - url = f"{url_to_fs}" |
28 |
| - |
29 |
| - options = {**DEFAULT_FILE_OPTIONS, **(file_options or {})} |
30 |
| - headers = {"x-upsert": str(options["upsert"])} |
31 |
| - files = None |
32 |
| - |
33 |
| - if isinstance(file_body, bytes): |
34 |
| - files = {"file": (path, file_body, options["contentType"])} |
35 |
| - headers["cache-control"] = f"max-age={options['cacheControl']}" |
36 |
| - else: |
37 |
| - headers["Content-Type"] = options["contentType"] |
38 |
| - file_body = file_body.encode('utf-8') |
39 |
| - |
40 |
| - response = requests.put(url, data=file_body, headers=headers, files=files) |
41 |
| - data = response.json() |
42 |
| - |
43 |
| - if response.ok: |
44 |
| - return {"data": {"path": path, "fullPath": data.get("Key")}, "error": None} |
45 |
| - else: |
46 |
| - return {"data": None, "error": data} |
47 |
| - |
48 | 30 | def render(self, document: Dict) -> Dict:
|
49 | 31 | assets = document.get('assets', []) + [{"path": "/index.html", "content": document['html']}]
|
50 | 32 | test = document.get('test', True)
|
51 | 33 | save = document.get('save', False)
|
52 | 34 |
|
53 | 35 | expires_in = document.get('expiresIn', 1)
|
54 |
| - |
55 |
| - # Initiate document rendering process |
56 |
| - information_response = requests.post( |
57 |
| - self._build_url("/api/docs/initiate"), |
58 |
| - headers={"x-api-key": self.api_key, "Content-Type": "application/json"}, |
59 |
| - json={"assets": assets} |
| 36 | + # Add expires_in (in days) to the current time to get the expiration time |
| 37 | + expires_at = int(time.time()) + (expires_in * 24 * 60 * 60) |
| 38 | + # Convert to timestamp with timezone |
| 39 | + expires_at = datetime.datetime.fromtimestamp(expires_at, timezone.utc).isoformat() |
| 40 | + |
| 41 | + files = ( |
| 42 | + ('options', (None, json.dumps({ |
| 43 | + 'test': test, |
| 44 | + 'host': save, |
| 45 | + 'expiresAt': expires_at, |
| 46 | + 'fileName': document.get('title', "document") |
| 47 | + }), 'application/json')), |
60 | 48 | )
|
61 | 49 |
|
| 50 | + for asset in assets: |
| 51 | + if asset and asset.get('path') == "/index.html": |
62 | 52 |
|
63 |
| - if information_response.status_code != 200: |
64 |
| - return { |
65 |
| - "file": None, |
66 |
| - "error": information_response.json().get('error', "An unknown error has occurred"), |
67 |
| - "info": {"status": information_response.status_code}, |
68 |
| - } |
69 |
| - |
70 |
| - response = information_response.json() |
71 |
| - signed_urls = response['signedUrls'] |
72 |
| - |
73 |
| - for e in signed_urls: |
74 |
| - asset = next((item for item in document.get('assets', []) if item['path'] == e['path']), None) |
75 |
| - |
76 |
| - if asset and asset.get('content'): |
77 |
| - self._upload_to_signed_url(e['signedUrl'], e['path'], asset['content']) |
78 |
| - |
79 |
| - elif e['path'] == "/index.html": |
80 | 53 | html_builder = _HtmlBuilder(document.get('title'))
|
81 | 54 | style_sheets = [asset['path'] for asset in document.get('assets', []) if asset['path'].endswith(".css")]
|
82 |
| - html = html_builder.build(document['html'], style_sheets, test) |
83 |
| - self._upload_to_signed_url(e['signedUrl'], e['path'], html) |
84 |
| - |
85 |
| - doc_response = requests.post( |
86 |
| - self._build_url("/api/docs/generate"), |
87 |
| - headers={"x-api-key": self.api_key, "Content-Type": "application/json"}, |
88 |
| - json=json.dumps({ |
89 |
| - "uploadURL":response["uploadURL"], |
90 |
| - "username":response["username"], |
91 |
| - "bucket":response["bucket"], |
92 |
| - "signedUrls":response["signedUrls"], |
93 |
| - "password":response["password"], |
94 |
| - "title": document.get('title', "document"), |
95 |
| - "test": test, |
96 |
| - "save": save, |
97 |
| - "expiresIn": expires_in |
98 |
| - }) |
| 55 | + html = html_builder.build(document['html'], style_sheets) |
| 56 | + |
| 57 | + files += ( |
| 58 | + ('files', ('index.html', html, 'text/html')), |
| 59 | + ) |
| 60 | + elif asset and asset.get('content'): |
| 61 | + files += ( |
| 62 | + ('files', (asset['path'], asset['content'], mimetypes.guess_type(asset['path'])[0] or 'application/octet-stream')), |
| 63 | + ) |
| 64 | + |
| 65 | + generation = requests.post( |
| 66 | + self._build_url("/pdf/generate"), |
| 67 | + headers={"x-api-key": self.api_key}, |
| 68 | + files=files |
99 | 69 | )
|
100 | 70 |
|
101 |
| - if doc_response.status_code != 200: |
102 |
| - return doc_response.__dict__ |
| 71 | + if generation.status_code != 201: |
| 72 | + return { |
| 73 | + "file": None, |
| 74 | + "link": None, |
| 75 | + "error": generation.json(), |
| 76 | + "info": {}, |
| 77 | + } |
103 | 78 |
|
104 | 79 | if not save:
|
105 | 80 | return {
|
106 |
| - "file": doc_response.content, |
| 81 | + "file": generation.content, |
107 | 82 | "link": None,
|
108 | 83 | "error": None,
|
109 | 84 | "info": {},
|
110 | 85 | }
|
111 | 86 | else:
|
112 | 87 | return {
|
113 | 88 | "file": None,
|
114 |
| - "link": doc_response.json().get('url_link'), |
| 89 | + "link": generation.json().get('url'), |
115 | 90 | "error": None,
|
116 | 91 | "info": {},
|
117 | 92 | }
|
|
0 commit comments