diff --git a/pyproject.toml b/pyproject.toml index d1f3a9f..da57b1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "python-substack" -version = "0.1.1" +version = "0.1.2" description = "A Python wrapper around the Substack API." authors = ["Paolo Mazza "] license = "MIT" diff --git a/substack/api.py b/substack/api.py index 3ae81ab..78ac64e 100644 --- a/substack/api.py +++ b/substack/api.py @@ -111,6 +111,12 @@ def get_drafts(self, filter: str = None, offset: int = None, limit: int = None): ) return Api._handle_response(response=response) + def delete_draft(self, draft_id): + response = self._session.delete( + f"{self.publication_url}/drafts/{draft_id}" + ) + return Api._handle_response(response=response) + def post_draft(self, body) -> dict: """ @@ -189,6 +195,15 @@ def publish_draft( ) return Api._handle_response(response=response) + def get_image(self, image): + response = self._session.post( + f"{self.publication_url}/image", + json={ + "image": image + }, + ) + return Api._handle_response(response=response) + def get_categories(self): """ @@ -235,3 +250,13 @@ def get_single_category(self, category_id: int, category_type: str, page: int | "more": page_output.get("more", False) } return output + + def delete_all_drafts(self): + response = None + while True: + drafts = self.get_drafts(filter="draft", limit=10, offset=0) + if len(drafts) == 0: + break + for draft in drafts: + response = self.delete_draft(draft.get("id")) + return response diff --git a/substack/post.py b/substack/post.py index f78d06c..d668b1a 100644 --- a/substack/post.py +++ b/substack/post.py @@ -12,11 +12,21 @@ def __init__(self, title: str, subtitle: str, user_id: str): def add(self, item): self.draft_body["content"] = self.draft_body.get("content", []) + [{"type": item.get("type")}] content = item.get("content") - if content is not None: - self.text(content) + if item.get("type") == "captionedImage": + self.captioned_image(item) + elif item.get("type") == "youtube2": + self.youtube(item.get("src")) + else: + if content is not None: + self.add_complex_text(content) if item.get("type") == "heading": self.attrs(item.get("level", 1)) + + marks = item.get("marks") + if marks is not None: + self.marks(marks) + return self def paragraph(self, content=None): @@ -41,6 +51,22 @@ def attrs(self, level): self.draft_body["content"][-1]["attrs"] = content_attrs return self + def captioned_image(self, value): + content = self.draft_body["content"][-1].get("content", []) + content += [{"type": "image2", "attrs": { + "src": value.get("src"), + "fullscreen": False, + "imageSize": value.get("size", "normal"), + "height": 819, + "width": 1456, + "resizeWidth": 728, + + "bytes": None, "alt": None, "title": None, "type": None, "href": None, "belowTheFold": False, + "internalRedirect": None + + }}] + self.draft_body["content"][-1]["content"] = content + def text(self, value: str): """ @@ -57,11 +83,25 @@ def text(self, value: str): self.draft_body["content"][-1]["content"] = content return self + def add_complex_text(self, text): + if isinstance(text, str): + self.text(text) + else: + for chunk in text: + if chunk: + self.text(chunk.get("content")).marks(chunk.get("marks")) + def marks(self, marks): content = self.draft_body["content"][-1].get("content", [])[-1] content_marks = content.get("marks", []) for mark in marks: - content_marks.append({"type": mark}) + new_mark = {"type": mark.get("type")} + if mark.get("type") == "link": + href = mark.get("href") + new_mark.update({"attrs": { + "href": href + }}) + content_marks.append(new_mark) content["marks"] = content_marks return self @@ -72,3 +112,23 @@ def get_draft(self): out = vars(self) out["draft_body"] = json.dumps(out["draft_body"]) return out + + def subscribe_with_caption(self, value): + content = self.draft_body["content"][-1].get("content", []) + content += [{"type": "subscribeWidget", + "attrs": {"url": "%%checkout_url%%", "text": "Subscribe"}, + "content": [ + { + "type": "ctaCaption", + "content": [{"type": "text", + "text": f"Thanks for reading {value}! Subscribe for free to receive new posts and support my work."}] + } + ]}] + self.draft_body["content"][-1]["content"] = content + return self + + def youtube(self, value): + content_attrs = self.draft_body["content"][-1].get("attrs", {}) + content_attrs.update({"videoId": value}) + self.draft_body["content"][-1]["attrs"] = content_attrs + return self