380 lines
13 KiB
Python
380 lines
13 KiB
Python
"""Provide the helper classes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from json import dumps
|
|
from typing import TYPE_CHECKING, Any, Generator
|
|
|
|
from ..const import API_PATH
|
|
from ..util import _deprecate_args
|
|
from .base import PRAWBase
|
|
from .reddit.draft import Draft
|
|
from .reddit.live import LiveThread
|
|
from .reddit.multi import Multireddit, Subreddit
|
|
|
|
if TYPE_CHECKING: # pragma: no cover
|
|
import praw.models
|
|
|
|
|
|
class DraftHelper(PRAWBase):
|
|
r"""Provide a set of functions to interact with :class:`.Draft` instances.
|
|
|
|
.. note::
|
|
|
|
The methods provided by this class will only work on the currently authenticated
|
|
user's :class:`.Draft`\ s.
|
|
|
|
"""
|
|
|
|
def __call__(
|
|
self, draft_id: str | None = None
|
|
) -> list[praw.models.Draft] | praw.models.Draft:
|
|
"""Return a list of :class:`.Draft` instances.
|
|
|
|
:param draft_id: When provided, this returns a :class:`.Draft` instance
|
|
(default: ``None``).
|
|
|
|
:returns: A :class:`.Draft` instance if ``draft_id`` is provided. Otherwise, a
|
|
list of :class:`.Draft` objects.
|
|
|
|
.. note::
|
|
|
|
Drafts fetched using a specific draft ID are lazily loaded, so you might
|
|
have to access an attribute to get all the expected attributes.
|
|
|
|
This method can be used to fetch a specific draft by ID, like so:
|
|
|
|
.. code-block:: python
|
|
|
|
draft_id = "124862bc-e1e9-11eb-aa4f-e68667a77cbb"
|
|
draft = reddit.drafts(draft_id)
|
|
print(draft)
|
|
|
|
"""
|
|
if draft_id is not None:
|
|
return Draft(self._reddit, id=draft_id)
|
|
return self._draft_list()
|
|
|
|
def _draft_list(self) -> list[praw.models.Draft]:
|
|
"""Get a list of :class:`.Draft` instances.
|
|
|
|
:returns: A list of :class:`.Draft` instances.
|
|
|
|
"""
|
|
return self._reddit.get(API_PATH["drafts"], params={"md_body": True})
|
|
|
|
def create(
|
|
self,
|
|
*,
|
|
flair_id: str | None = None,
|
|
flair_text: str | None = None,
|
|
is_public_link: bool = False,
|
|
nsfw: bool = False,
|
|
original_content: bool = False,
|
|
selftext: str | None = None,
|
|
send_replies: bool = True,
|
|
spoiler: bool = False,
|
|
subreddit: (
|
|
str | praw.models.Subreddit | praw.models.UserSubreddit | None
|
|
) = None,
|
|
title: str | None = None,
|
|
url: str | None = None,
|
|
**draft_kwargs: Any,
|
|
) -> praw.models.Draft:
|
|
"""Create a new :class:`.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 is_public_link: Whether to enable public viewing of the draft before it
|
|
is submitted (default: ``False``).
|
|
:param nsfw: Whether the draft should be marked NSFW (default: ``False``).
|
|
:param original_content: Whether the submission should be marked as original
|
|
content (default: ``False``).
|
|
:param selftext: The Markdown formatted content for a text submission draft. Use
|
|
``None`` to make a title-only submission draft (default: ``None``).
|
|
``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 (default: ``True``).
|
|
:param spoiler: Whether the submission should be marked as a spoiler (default:
|
|
``False``).
|
|
:param subreddit: The subreddit to create the draft for. This accepts a
|
|
subreddit display name, :class:`.Subreddit` object, or
|
|
:class:`.UserSubreddit` object. If ``None``, the :class:`.UserSubreddit` of
|
|
currently authenticated user will be used (default: ``None``).
|
|
:param title: The title of the draft (default: ``None``).
|
|
:param url: The URL for a ``link`` submission draft (default: ``None``). ``url``
|
|
can not be provided if ``selftext`` is provided.
|
|
|
|
Additional keyword arguments can be provided to handle new parameters as Reddit
|
|
introduces them.
|
|
|
|
:returns: The new :class:`.Draft` object.
|
|
|
|
"""
|
|
if selftext and url:
|
|
msg = "Exactly one of 'selftext' or 'url' must be provided."
|
|
raise TypeError(msg)
|
|
if isinstance(subreddit, str):
|
|
subreddit = self._reddit.subreddit(subreddit)
|
|
|
|
data = Draft._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,
|
|
)
|
|
return self._reddit.post(API_PATH["draft"], data=data)
|
|
|
|
|
|
class LiveHelper(PRAWBase):
|
|
r"""Provide a set of functions to interact with :class:`.LiveThread`\ s."""
|
|
|
|
def __call__(self, id: str) -> praw.models.LiveThread:
|
|
"""Return a new lazy instance of :class:`.LiveThread`.
|
|
|
|
This method is intended to be used as:
|
|
|
|
.. code-block:: python
|
|
|
|
livethread = reddit.live("ukaeu1ik4sw5")
|
|
|
|
:param id: A live thread ID, e.g., ``ukaeu1ik4sw5``.
|
|
|
|
"""
|
|
return LiveThread(self._reddit, id=id)
|
|
|
|
@_deprecate_args("title", "description", "nsfw", "resources")
|
|
def create(
|
|
self,
|
|
title: str,
|
|
*,
|
|
description: str | None = None,
|
|
nsfw: bool = False,
|
|
resources: str = None,
|
|
) -> praw.models.LiveThread:
|
|
"""Create a new :class:`.LiveThread`.
|
|
|
|
:param title: The title of the new :class:`.LiveThread`.
|
|
:param description: The new :class:`.LiveThread`'s description.
|
|
:param nsfw: Indicate whether this thread is not safe for work (default:
|
|
``False``).
|
|
:param resources: Markdown formatted information that is useful for the
|
|
:class:`.LiveThread`.
|
|
|
|
:returns: The new :class:`.LiveThread` object.
|
|
|
|
"""
|
|
return self._reddit.post(
|
|
API_PATH["livecreate"],
|
|
data={
|
|
"description": description,
|
|
"nsfw": nsfw,
|
|
"resources": resources,
|
|
"title": title,
|
|
},
|
|
)
|
|
|
|
def info(self, ids: list[str]) -> Generator[praw.models.LiveThread, None, None]:
|
|
"""Fetch information about each live thread in ``ids``.
|
|
|
|
:param ids: A list of IDs for a live thread.
|
|
|
|
:returns: A generator that yields :class:`.LiveThread` instances.
|
|
|
|
:raises: ``prawcore.ServerError`` if invalid live threads are requested.
|
|
|
|
Requests will be issued in batches for each 100 IDs.
|
|
|
|
.. note::
|
|
|
|
This method doesn't support IDs for live updates.
|
|
|
|
.. warning::
|
|
|
|
Unlike :meth:`.Reddit.info`, the output of this method may not reflect the
|
|
order of input.
|
|
|
|
Usage:
|
|
|
|
.. code-block:: python
|
|
|
|
ids = ["3rgnbke2rai6hen7ciytwcxadi", "sw7bubeycai6hey4ciytwamw3a", "t8jnufucss07"]
|
|
for thread in reddit.live.info(ids):
|
|
print(thread.title)
|
|
|
|
"""
|
|
if not isinstance(ids, list):
|
|
msg = "ids must be a list"
|
|
raise TypeError(msg)
|
|
|
|
def generator():
|
|
for position in range(0, len(ids), 100):
|
|
ids_chunk = ids[position : position + 100]
|
|
url = API_PATH["live_info"].format(ids=",".join(ids_chunk))
|
|
params = {"limit": 100} # 25 is used if not specified
|
|
yield from self._reddit.get(url, params=params)
|
|
|
|
return generator()
|
|
|
|
def now(self) -> praw.models.LiveThread | None:
|
|
"""Get the currently featured live thread.
|
|
|
|
:returns: The :class:`.LiveThread` object, or ``None`` if there is no currently
|
|
featured live thread.
|
|
|
|
Usage:
|
|
|
|
.. code-block:: python
|
|
|
|
thread = reddit.live.now() # LiveThread object or None
|
|
|
|
"""
|
|
return self._reddit.get(API_PATH["live_now"])
|
|
|
|
|
|
class MultiredditHelper(PRAWBase):
|
|
"""Provide a set of functions to interact with multireddits."""
|
|
|
|
@_deprecate_args("redditor", "name")
|
|
def __call__(
|
|
self, *, name: str, redditor: str | praw.models.Redditor
|
|
) -> praw.models.Multireddit:
|
|
"""Return a lazy instance of :class:`.Multireddit`.
|
|
|
|
:param name: The name of the multireddit.
|
|
:param redditor: A redditor name or :class:`.Redditor` instance who owns the
|
|
multireddit.
|
|
|
|
"""
|
|
path = f"/user/{redditor}/m/{name}"
|
|
return Multireddit(self._reddit, _data={"name": name, "path": path})
|
|
|
|
@_deprecate_args(
|
|
"display_name",
|
|
"subreddits",
|
|
"description_md",
|
|
"icon_name",
|
|
"key_color",
|
|
"visibility",
|
|
"weighting_scheme",
|
|
)
|
|
def create(
|
|
self,
|
|
*,
|
|
description_md: str | None = None,
|
|
display_name: str,
|
|
icon_name: str | None = None,
|
|
key_color: str | None = None,
|
|
subreddits: str | praw.models.Subreddit,
|
|
visibility: str = "private",
|
|
weighting_scheme: str = "classic",
|
|
) -> praw.models.Multireddit:
|
|
"""Create a new :class:`.Multireddit`.
|
|
|
|
:param display_name: The display name for the new multireddit.
|
|
:param subreddits: Subreddits to add to the new multireddit. Can be a list of
|
|
either :class:`.Subreddit` instances or subreddit display names.
|
|
:param description_md: Description for the new multireddit, formatted in
|
|
markdown.
|
|
:param icon_name: Can be one of: ``"art and design"``, ``"ask"``, ``"books"``,
|
|
``"business"``, ``"cars"``, ``"comics"``, ``"cute animals"``, ``"diy"``,
|
|
``"entertainment"``, ``"food and drink"``, ``"funny"``, ``"games"``,
|
|
``"grooming"``, ``"health"``, ``"life advice"``, ``"military"``, ``"models
|
|
pinup"``, ``"music"``, ``"news"``, ``"philosophy"``, ``"pictures and
|
|
gifs"``, ``"science"``, ``"shopping"``, ``"sports"``, ``"style"``,
|
|
``"tech"``, ``"travel"``, ``"unusual stories"``, ``"video"``, or ``None``.
|
|
:param key_color: RGB hex color code of the form ``"#FFFFFF"``.
|
|
:param visibility: Can be one of: ``"hidden"``, ``"private"``, or ``"public"``
|
|
(default: ``"private"``).
|
|
:param weighting_scheme: Can be one of: ``"classic"`` or ``"fresh"`` (default:
|
|
``"classic"``).
|
|
|
|
:returns: The new :class:`.Multireddit` object.
|
|
|
|
"""
|
|
model = {
|
|
"description_md": description_md,
|
|
"display_name": display_name,
|
|
"icon_name": icon_name,
|
|
"key_color": key_color,
|
|
"subreddits": [{"name": str(sub)} for sub in subreddits],
|
|
"visibility": visibility,
|
|
"weighting_scheme": weighting_scheme,
|
|
}
|
|
return self._reddit.post(
|
|
API_PATH["multireddit_base"], data={"model": dumps(model)}
|
|
)
|
|
|
|
|
|
class SubredditHelper(PRAWBase):
|
|
"""Provide a set of functions to interact with Subreddits."""
|
|
|
|
def __call__(self, display_name: str) -> praw.models.Subreddit:
|
|
"""Return a lazy instance of :class:`.Subreddit`.
|
|
|
|
:param display_name: The name of the subreddit.
|
|
|
|
"""
|
|
lower_name = display_name.lower()
|
|
|
|
if lower_name == "random":
|
|
return self._reddit.random_subreddit()
|
|
if lower_name == "randnsfw":
|
|
return self._reddit.random_subreddit(nsfw=True)
|
|
|
|
return Subreddit(self._reddit, display_name=display_name)
|
|
|
|
@_deprecate_args("name", "title", "link_type", "subreddit_type", "wikimode")
|
|
def create(
|
|
self,
|
|
name: str,
|
|
*,
|
|
link_type: str = "any",
|
|
subreddit_type: str = "public",
|
|
title: str | None = None,
|
|
wikimode: str = "disabled",
|
|
**other_settings: str | None,
|
|
) -> praw.models.Subreddit:
|
|
"""Create a new :class:`.Subreddit`.
|
|
|
|
:param name: The name for the new subreddit.
|
|
:param link_type: The types of submissions users can make. One of ``"any"``,
|
|
``"link"``, or ``"self"`` (default: ``"any"``).
|
|
:param subreddit_type: One of ``"archived"``, ``"employees_only"``,
|
|
``"gold_only"``, ``"gold_restricted"``, ``"private"``, ``"public"``, or
|
|
``"restricted"`` (default: ``"public"``).
|
|
:param title: The title of the subreddit. When ``None`` or ``""`` use the value
|
|
of ``name``.
|
|
:param wikimode: One of ``"anyone"``, ``"disabled"``, or ``"modonly"`` (default:
|
|
``"disabled"``).
|
|
|
|
Any keyword parameters not provided, or set explicitly to ``None``, will take on
|
|
a default value assigned by the Reddit server.
|
|
|
|
.. seealso::
|
|
|
|
:meth:`~.SubredditModeration.update` for documentation of other available
|
|
settings.
|
|
|
|
"""
|
|
Subreddit._create_or_update(
|
|
_reddit=self._reddit,
|
|
link_type=link_type,
|
|
name=name,
|
|
subreddit_type=subreddit_type,
|
|
title=title or name,
|
|
wikimode=wikimode,
|
|
**other_settings,
|
|
)
|
|
return self(name)
|