diff --git a/examples/draft.yaml b/examples/draft.yaml index bb739a1..e49f9ff 100644 --- a/examples/draft.yaml +++ b/examples/draft.yaml @@ -2,6 +2,10 @@ title: "How to publish a Substack post using the Python API" subtitle: "This post was published using the Python API" +audience: + "everyone" # everyone, only_paid, founding, only_free +write_comment_permissions: + "none" # none, only_paid, everyone body: 0: type: "heading" @@ -12,7 +16,7 @@ body: content: "1)" 2: type: "paragraph" - content: "Discover your USER ID by inspecting the request body of any publish request." + content: "discover the USER_ID in the url of the public profile page" 3: type: "horizontal_rule" 4: diff --git a/examples/publish_post.py b/examples/publish_post.py index 07ac152..07f6d07 100644 --- a/examples/publish_post.py +++ b/examples/publish_post.py @@ -20,17 +20,20 @@ with open(args.post, "r") as fp: post_data = yaml.safe_load(fp) - title = post_data.get("title", "") - subtitle = post_data.get("subtitle", "") - body = post_data.get("body", {}) - api = Api( email=os.getenv("EMAIL"), password=os.getenv("PASSWORD"), publication_url=os.getenv("PUBLICATION_URL"), ) - post = Post(title, subtitle, os.getenv("USER_ID")) + post = Post(post_data.get("title"), + post_data.get("subtitle", ""), + os.getenv("USER_ID"), + audience=post_data.get("audience", "everyone"), + write_comment_permissions=post_data.get("write_comment_permissions", "everyone")) + + body = post_data.get("body", {}) + for _, item in body.items(): if item.get("type") == "captionedImage": image = api.get_image(item.get("src")) diff --git a/pyproject.toml b/pyproject.toml index 95a9024..34f17da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "python-substack" -version = "0.1.7" +version = "0.1.8" description = "A Python wrapper around the Substack API." authors = ["Paolo Mazza "] license = "MIT" diff --git a/substack/post.py b/substack/post.py index 54a26a1..b83a58c 100644 --- a/substack/post.py +++ b/substack/post.py @@ -4,15 +4,35 @@ class Post: - def __init__(self, title, subtitle, user_id): + def __init__(self, title: str, subtitle: str, user_id, + audience: str = None, + write_comment_permissions: str = None): + """ + + Args: + title: + subtitle: + user_id: + audience: possible values: everyone, only_paid, founding, only_free + write_comment_permissions: none, only_paid, everyone (this field is a mess) + """ self.draft_title = title self.draft_subtitle = subtitle self.draft_body = {"type": "doc", "content": []} self.draft_bylines = [{"id": int(user_id), "is_guest": False}] + self.audience = audience if audience is not None else "everyone" + + # TODO better understand the possible values and combinations with audience + if write_comment_permissions is not None: + self.write_comment_permissions = write_comment_permissions + else: + self.write_comment_permissions = self.audience def add(self, item: Dict): """ + Add item to draft body. + Args: item: @@ -40,12 +60,30 @@ def add(self, item: Dict): return self def paragraph(self, content=None): + """ + + Args: + content: + + Returns: + + """ item = {"type": "paragraph"} if content is not None: item["content"] = content return self.add(item) - def heading(self, content=None, level=1): + def heading(self, content=None, level: int = 1): + """ + + Args: + content: + level: + + Returns: + + """ + item = {"type": "heading"} if content is not None: item["content"] = content @@ -53,9 +91,22 @@ def heading(self, content=None, level=1): return self.add(item) def horizontal_rule(self): + """ + + Returns: + + """ return self.add({"type": "horizontal_rule"}) def attrs(self, level): + """ + + Args: + level: + + Returns: + + """ content_attrs = self.draft_body["content"][-1].get("attrs", {}) content_attrs.update({"level": level}) self.draft_body["content"][-1]["attrs"] = content_attrs @@ -116,7 +167,7 @@ def captioned_image(self, self.draft_body["content"][-1]["content"] = content return self - def text(self, value): + def text(self, value: str): """ Add text to the last paragraph. @@ -133,6 +184,11 @@ def text(self, value): return self def add_complex_text(self, text): + """ + + Args: + text: + """ if isinstance(text, str): self.text(text) else: @@ -141,6 +197,14 @@ def add_complex_text(self, text): self.text(chunk.get("content")).marks(chunk.get("marks")) def marks(self, marks): + """ + + Args: + marks: + + Returns: + + """ content = self.draft_body["content"][-1].get("content", [])[-1] content_marks = content.get("marks", []) for mark in marks: @@ -155,14 +219,30 @@ def marks(self, marks): return self def remove_last_paragraph(self): + """ + + """ del self.draft_body.get("content")[-1] def get_draft(self): + """ + + Returns: + + """ out = vars(self) out["draft_body"] = json.dumps(out["draft_body"]) return out - def subscribe_with_caption(self, value): + def subscribe_with_caption(self, value: str): + """ + + Args: + value: + + Returns: + + """ content = self.draft_body["content"][-1].get("content", []) content += [{"type": "subscribeWidget", "attrs": {"url": "%%checkout_url%%", "text": "Subscribe"}, @@ -177,7 +257,15 @@ def subscribe_with_caption(self, value): self.draft_body["content"][-1]["content"] = content return self - def youtube(self, value): + def youtube(self, value: str): + """ + + Args: + value: + + Returns: + + """ content_attrs = self.draft_body["content"][-1].get("attrs", {}) content_attrs.update({"videoId": value}) self.draft_body["content"][-1]["attrs"] = content_attrs