Skip to content

adds support for selftext in link, image, gallery, and video posts #2067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ Source Contributors
- zacc `@zacc <https://github.com/zacc>`_
- c0d3rman `@c0d3rman <https://github.com/c0d3rman>`_
- Joe Kerhin `@jkerhin <https://github.com/jkerhin>`_
- Aaron Becker `@aaronjbecker <https://github.com/aaronjbecker>`_
- Add "Name <email (optional)> and github profile link" above this line.
10 changes: 10 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Unreleased
**Added**

- Add support for Python 3.13.
- Add support for optional Markdown-formatted ``selftext`` when submitting link, image,
gallery and video posts.

**Changed**

Expand All @@ -23,6 +25,14 @@ Unreleased
must now be passed by keyword.
- The ``flair_type`` argument to :class:`.SubredditFlairTemplates` must be passed by
keyword.
- The ``selftext`` and ``url`` arguments to :meth:`.Subreddit.submit` are no longer
mutually exclusive. When ``url`` is provided ``selftext`` will be used as optional
body text to accompany the link submission. An exception is raised when trying to use
``inline_media`` with ``selftext`` for a ``url`` submission because Reddit does not
support inline media in body text for link submissions.
- :meth:`.Subreddit.submit_video`, :meth:`.Subreddit.submit_gallery`, and
:meth:`.Subreddit.submit_image` now accept an optional Markdown-formatted ``selftext``
parameter.

**Removed**

Expand Down
54 changes: 42 additions & 12 deletions praw/models/reddit/subreddit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2889,22 +2889,27 @@ def _upload_media(
self,
*,
expected_mime_prefix: str | None = None,
media_path: str,
media_path: str | None,
upload_type: str = "link",
) -> str:
"""Upload media and return its URL and a websocket (Undocumented endpoint).

:param expected_mime_prefix: If provided, enforce that the media has a mime type
that starts with the provided prefix.
:param media_path: The path to the media file to upload. Default is the PRAW
logo.
:param upload_type: One of ``"link"``, ``"gallery"'', or ``"selfpost"``
(default: ``"link"``).

:returns: The link to the uploaded media.

"""
if media_path is None:
file = Path(__file__).absolute()
media_path = file.parent.parent.parent / "images" / "PRAW logo.png"
# if we're uploading without a media path, assume we're uploading a PRAW logo
# this default is commonly used when ``video_poster_url`` is not provided in ``submit_video``
module_path = Path(__file__).absolute()
logo_path = module_path.parent.parent.parent / "images" / "PRAW logo.png"
file = Path(logo_path)
else:
file = Path(media_path)

Expand Down Expand Up @@ -3073,12 +3078,14 @@ def submit(
this value will set a custom text (default: ``None``). ``flair_id`` is
required when ``flair_text`` is provided.
:param inline_media: A dict of :class:`.InlineMedia` objects where the key is
the placeholder name in ``selftext``.
the placeholder name in ``selftext``. Link post selftext does not support
inline media.
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
:param resubmit: When ``False``, an error will occur if the URL has already been
submitted (default: ``True``).
:param selftext: The Markdown formatted content for a ``text`` submission. Use
an empty string, ``""``, to make a title-only submission.
:param selftext: The Markdown formatted content for a ``text`` submission or an
optional post body for ``link`` submissions. Use an empty string, ``""``, to
make a title-only submission.
: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:
Expand All @@ -3087,7 +3094,10 @@ def submit(

:returns: A :class:`.Submission` object for the newly created submission.

Either ``selftext`` or ``url`` can be provided, but not both.
Provide ``selftext`` alone for a ``text`` submission. ``selftext`` can accompany
a ``url`` for a ``link`` submission. ``selftext`` that accompanies a ``link``
submission is optional. ``selftext`` for ``link`` submissions does not support
``inline_media``.

For example, to submit a URL to r/test do:

Expand Down Expand Up @@ -3152,8 +3162,10 @@ def submit(
- :meth:`~.Subreddit.submit_video` to submit videos and videogifs

"""
if (bool(selftext) or selftext == "") == bool(url): # noqa: PLC1901
msg = "Either 'selftext' or 'url' must be provided."
# link posts can now include selftext (no longer exclusive)
# test for empty string in selftext for title-only submissions
if not url and not (bool(selftext) or selftext == ""): # noqa: PLC1901
msg = "Submission requires either 'selftext' or 'url' to be provided."
raise TypeError(msg)

data = {
Expand All @@ -3174,7 +3186,15 @@ def submit(
):
if value is not None:
data[key] = value
if selftext is not None:
if url is not None:
data.update(kind="link", url=url)
if inline_media:
msg = "As of 2025-05-07, `inline_media` is not supported for link post selftext. Only Markdown text can be added to non-self posts."
raise TypeError(msg)
# we can ignore an empty string for selftext here b/c body text is optional for link posts
if selftext:
data.update(text=selftext)
elif selftext is not None:
data.update(kind="self")
if inline_media:
body = selftext.format(**{
Expand All @@ -3184,8 +3204,6 @@ def submit(
data.update(richtext_json=dumps(converted))
else:
data.update(text=selftext)
else:
data.update(kind="link", url=url)

return self._reddit.post(API_PATH["submit"], data=data)

Expand All @@ -3199,6 +3217,7 @@ def submit_gallery(
flair_id: str | None = None,
flair_text: str | None = None,
nsfw: bool = False,
selftext: str | None = None,
send_replies: bool = True,
spoiler: bool = False,
) -> praw.models.Submission:
Expand All @@ -3217,6 +3236,8 @@ def submit_gallery(
this value will set a custom text (default: ``None``). ``flair_id`` is
required when ``flair_text`` is provided.
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
:param selftext: Optional Markdown-formatted post body content (default:
``None``).
: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 asa spoiler (default:
Expand Down Expand Up @@ -3274,6 +3295,7 @@ def submit_gallery(
("flair_text", flair_text),
("collection_id", collection_id),
("discussion_type", discussion_type),
("text", selftext),
):
if value is not None:
data[key] = value
Expand Down Expand Up @@ -3303,6 +3325,7 @@ def submit_image(
flair_text: str | None = None,
nsfw: bool = False,
resubmit: bool = True,
selftext: str | None = None,
send_replies: bool = True,
spoiler: bool = False,
timeout: int = 10,
Expand All @@ -3322,6 +3345,8 @@ def submit_image(
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
:param resubmit: When ``False``, an error will occur if the URL has already been
submitted (default: ``True``).
:param selftext: Optional Markdown-formatted post body content (default:
``None``).
: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:
Expand Down Expand Up @@ -3383,6 +3408,7 @@ def submit_image(
("flair_text", flair_text),
("collection_id", collection_id),
("discussion_type", discussion_type),
("text", selftext),
):
if value is not None:
data[key] = value
Expand Down Expand Up @@ -3485,6 +3511,7 @@ def submit_video(
flair_text: str | None = None,
nsfw: bool = False,
resubmit: bool = True,
selftext: str | None = None,
send_replies: bool = True,
spoiler: bool = False,
thumbnail_path: str | None = None,
Expand All @@ -3507,6 +3534,8 @@ def submit_video(
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
:param resubmit: When ``False``, an error will occur if the URL has already been
submitted (default: ``True``).
:param selftext: Optional Markdown-formatted post body content (default:
``None``).
: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:
Expand Down Expand Up @@ -3572,6 +3601,7 @@ def submit_video(
("flair_text", flair_text),
("collection_id", collection_id),
("discussion_type", discussion_type),
("text", selftext),
):
if value is not None:
data[key] = value
Expand Down
Loading