309 lines
12 KiB
Python
309 lines
12 KiB
Python
"""Provide the draft class."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from ...const import API_PATH
|
|
from ...exceptions import ClientException
|
|
from .base import RedditBase
|
|
from .subreddit import Subreddit
|
|
from .user_subreddit import UserSubreddit
|
|
|
|
if TYPE_CHECKING: # pragma: no cover
|
|
import praw.models
|
|
|
|
|
|
class Draft(RedditBase):
|
|
"""A class that represents a Reddit submission draft.
|
|
|
|
.. include:: ../../typical_attributes.rst
|
|
|
|
========================== ======================================================
|
|
Attribute Description
|
|
========================== ======================================================
|
|
``link_flair_template_id`` The link flair's ID.
|
|
``link_flair_text`` The link flair's text content, or ``None`` if not
|
|
flaired.
|
|
``modified`` Time the submission draft was modified, represented in
|
|
`Unix Time`_.
|
|
``original_content`` Whether the submission draft will be set as original
|
|
content.
|
|
``selftext`` The submission draft's selftext. ``None`` if a link
|
|
submission draft.
|
|
``spoiler`` Whether the submission will be marked as a spoiler.
|
|
``subreddit`` Provides an instance of :class:`.Subreddit` or
|
|
:class:`.UserSubreddit` (if set).
|
|
``title`` The title of the submission draft.
|
|
``url`` The URL the submission draft links to.
|
|
========================== ======================================================
|
|
|
|
.. _unix time: https://en.wikipedia.org/wiki/Unix_time
|
|
|
|
"""
|
|
|
|
STR_FIELD = "id"
|
|
|
|
@classmethod
|
|
def _prepare_data(
|
|
cls,
|
|
*,
|
|
flair_id: str | None = None,
|
|
flair_text: str | None = None,
|
|
is_public_link: bool | None = None,
|
|
nsfw: bool | None = None,
|
|
original_content: bool | None = None,
|
|
selftext: str | None = None,
|
|
send_replies: bool | None = None,
|
|
spoiler: bool | None = None,
|
|
subreddit: praw.models.Subreddit | praw.models.UserSubreddit | None = None,
|
|
title: str | None = None,
|
|
url: str | None = None,
|
|
**draft_kwargs: Any,
|
|
) -> dict[str, Any]:
|
|
data = {
|
|
"body": selftext or url,
|
|
"flair_id": flair_id,
|
|
"flair_text": flair_text,
|
|
"is_public_link": is_public_link,
|
|
"kind": "markdown" if selftext is not None else "link",
|
|
"nsfw": nsfw,
|
|
"original_content": original_content,
|
|
"send_replies": send_replies,
|
|
"spoiler": spoiler,
|
|
"title": title,
|
|
}
|
|
if subreddit:
|
|
data.update(
|
|
{
|
|
"subreddit": subreddit.fullname,
|
|
"target": (
|
|
"profile"
|
|
if subreddit.display_name.startswith("u_")
|
|
else "subreddit"
|
|
),
|
|
}
|
|
)
|
|
data.update(draft_kwargs)
|
|
return data
|
|
|
|
def __init__(
|
|
self, reddit: praw.Reddit, id: str | None = None, _data: dict[str, Any] = None
|
|
):
|
|
"""Initialize a :class:`.Draft` instance."""
|
|
if (id, _data).count(None) != 1:
|
|
msg = "Exactly one of 'id' or '_data' must be provided."
|
|
raise TypeError(msg)
|
|
fetched = False
|
|
if id:
|
|
self.id = id
|
|
elif len(_data) > 1:
|
|
if _data["kind"] == "markdown":
|
|
_data["selftext"] = _data.pop("body")
|
|
elif _data["kind"] == "link":
|
|
_data["url"] = _data.pop("body")
|
|
fetched = True
|
|
super().__init__(reddit, _data=_data, _fetched=fetched)
|
|
|
|
def __repr__(self) -> str:
|
|
"""Return an object initialization representation of the instance."""
|
|
if self._fetched:
|
|
subreddit = (
|
|
f" subreddit={self.subreddit.display_name!r}" if self.subreddit else ""
|
|
)
|
|
title = f" title={self.title!r}" if self.title else ""
|
|
return f"{self.__class__.__name__}(id={self.id!r}{subreddit}{title})"
|
|
return f"{self.__class__.__name__}(id={self.id!r})"
|
|
|
|
def _fetch(self):
|
|
for draft in self._reddit.drafts():
|
|
if draft.id == self.id:
|
|
self.__dict__.update(draft.__dict__)
|
|
super()._fetch()
|
|
return
|
|
msg = (
|
|
f"The currently authenticated user not have a draft with an ID of {self.id}"
|
|
)
|
|
raise ClientException(msg)
|
|
|
|
def delete(self):
|
|
"""Delete the :class:`.Draft`.
|
|
|
|
Example usage:
|
|
|
|
.. code-block:: python
|
|
|
|
draft = reddit.drafts("124862bc-e1e9-11eb-aa4f-e68667a77cbb")
|
|
draft.delete()
|
|
|
|
"""
|
|
self._reddit.delete(API_PATH["draft"], params={"draft_id": self.id})
|
|
|
|
def submit(
|
|
self,
|
|
*,
|
|
flair_id: str | None = None,
|
|
flair_text: str | None = None,
|
|
nsfw: bool | None = None,
|
|
selftext: str | None = None,
|
|
spoiler: bool | None = None,
|
|
subreddit: (
|
|
str | praw.models.Subreddit | praw.models.UserSubreddit | None
|
|
) = None,
|
|
title: str | None = None,
|
|
url: str | None = None,
|
|
**submit_kwargs: Any,
|
|
) -> praw.models.Submission:
|
|
"""Submit a draft.
|
|
|
|
:param flair_id: The flair template to select (default: ``None``).
|
|
:param flair_text: If the template's ``flair_text_editable`` value is ``True``,
|
|
this value will set a custom text (default: ``None``). ``flair_id`` is
|
|
required when ``flair_text`` is provided.
|
|
:param nsfw: Whether or not the submission should be marked NSFW (default:
|
|
``None``).
|
|
:param selftext: The Markdown formatted content for a ``text`` submission. Use
|
|
an empty string, ``""``, to make a title-only submission (default:
|
|
``None``).
|
|
:param spoiler: Whether or not the submission should be marked as a spoiler
|
|
(default: ``None``).
|
|
:param subreddit: The subreddit to submit the draft to. This accepts a subreddit
|
|
display name, :class:`.Subreddit` object, or :class:`.UserSubreddit` object.
|
|
:param title: The title of the submission (default: ``None``).
|
|
:param url: The URL for a ``link`` submission (default: ``None``).
|
|
|
|
:returns: A :class:`.Submission` object for the newly created submission.
|
|
|
|
.. note::
|
|
|
|
Parameters set here will override their respective :class:`.Draft`
|
|
attributes.
|
|
|
|
Additional keyword arguments are passed to the :meth:`.Subreddit.submit` method.
|
|
|
|
For example, to submit a draft as is:
|
|
|
|
.. code-block:: python
|
|
|
|
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e")
|
|
submission = draft.submit()
|
|
|
|
For example, to submit a draft but use a different title than what is set:
|
|
|
|
.. code-block:: python
|
|
|
|
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e")
|
|
submission = draft.submit(title="New Title")
|
|
|
|
.. seealso::
|
|
|
|
- :meth:`~.Subreddit.submit` to submit url posts and selftexts
|
|
- :meth:`~.Subreddit.submit_gallery`. to submit more than one image in the
|
|
same post
|
|
- :meth:`~.Subreddit.submit_image` to submit images
|
|
- :meth:`~.Subreddit.submit_poll` to submit polls
|
|
- :meth:`~.Subreddit.submit_video` to submit videos and videogifs
|
|
|
|
"""
|
|
submit_kwargs["draft_id"] = self.id
|
|
if not (self.subreddit or subreddit):
|
|
msg = "'subreddit' must be set on the Draft instance or passed as a keyword argument."
|
|
raise ValueError(msg)
|
|
for key, attribute in [
|
|
("flair_id", flair_id),
|
|
("flair_text", flair_text),
|
|
("nsfw", nsfw),
|
|
("selftext", selftext),
|
|
("spoiler", spoiler),
|
|
("title", title),
|
|
("url", url),
|
|
]:
|
|
value = attribute or getattr(self, key, None)
|
|
if value is not None:
|
|
submit_kwargs[key] = value
|
|
if isinstance(subreddit, str):
|
|
_subreddit = self._reddit.subreddit(subreddit)
|
|
elif isinstance(subreddit, (Subreddit, UserSubreddit)):
|
|
_subreddit = subreddit
|
|
else:
|
|
_subreddit = self.subreddit
|
|
return _subreddit.submit(**submit_kwargs)
|
|
|
|
def update(
|
|
self,
|
|
*,
|
|
flair_id: str | None = None,
|
|
flair_text: str | None = None,
|
|
is_public_link: bool | None = None,
|
|
nsfw: bool | None = None,
|
|
original_content: bool | None = None,
|
|
selftext: str | None = None,
|
|
send_replies: bool | None = None,
|
|
spoiler: bool | None = None,
|
|
subreddit: (
|
|
str | praw.models.Subreddit | praw.models.UserSubreddit | None
|
|
) = None,
|
|
title: str | None = None,
|
|
url: str | None = None,
|
|
**draft_kwargs: Any,
|
|
):
|
|
"""Update the :class:`.Draft`.
|
|
|
|
.. note::
|
|
|
|
Only provided values will be updated.
|
|
|
|
:param flair_id: The flair template to select.
|
|
:param flair_text: If the template's ``flair_text_editable`` value is ``True``,
|
|
this value will set a custom text. ``flair_id`` is required when
|
|
``flair_text`` is provided.
|
|
:param is_public_link: Whether to enable public viewing of the draft before it
|
|
is submitted.
|
|
:param nsfw: Whether the draft should be marked NSFW.
|
|
:param original_content: Whether the submission should be marked as original
|
|
content.
|
|
:param selftext: The Markdown formatted content for a text submission draft. Use
|
|
``None`` to make a title-only submission draft. ``selftext`` can not be
|
|
provided if ``url`` is provided.
|
|
:param send_replies: When ``True``, messages will be sent to the submission
|
|
author when comments are made to the submission.
|
|
:param spoiler: Whether the submission should be marked as a spoiler.
|
|
:param subreddit: The subreddit to create the draft for. This accepts a
|
|
subreddit display name, :class:`.Subreddit` object, or
|
|
:class:`.UserSubreddit` object.
|
|
:param title: The title of the draft.
|
|
:param url: The URL for a ``link`` submission draft. ``url`` can not be provided
|
|
if ``selftext`` is provided.
|
|
|
|
Additional keyword arguments can be provided to handle new parameters as Reddit
|
|
introduces them.
|
|
|
|
For example, to update the title of a draft do:
|
|
|
|
.. code-block:: python
|
|
|
|
draft = reddit.drafts("5f87d55c-e4fb-11eb-8965-6aeb41b0880e")
|
|
draft.update(title="New title")
|
|
|
|
"""
|
|
if isinstance(subreddit, str):
|
|
subreddit = self._reddit.subreddit(subreddit)
|
|
data = self._prepare_data(
|
|
flair_id=flair_id,
|
|
flair_text=flair_text,
|
|
is_public_link=is_public_link,
|
|
nsfw=nsfw,
|
|
original_content=original_content,
|
|
selftext=selftext,
|
|
send_replies=send_replies,
|
|
spoiler=spoiler,
|
|
subreddit=subreddit,
|
|
title=title,
|
|
url=url,
|
|
**draft_kwargs,
|
|
)
|
|
data["id"] = self.id
|
|
_new_draft = self._reddit.put(API_PATH["draft"], data=data)
|
|
_new_draft._fetch()
|
|
self.__dict__.update(_new_draft.__dict__)
|