Skip to content

Commit 19e8d5c

Browse files
authored
Add support for selftext in link, image, gallery, and video posts (praw-dev#2067)
1 parent a580ebc commit 19e8d5c

9 files changed

Lines changed: 3529 additions & 19 deletions

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,5 @@ Source Contributors
8686
- zacc `@zacc <https://github.com/zacc>`_
8787
- c0d3rman `@c0d3rman <https://github.com/c0d3rman>`_
8888
- Joe Kerhin `@jkerhin <https://github.com/jkerhin>`_
89+
- Aaron Becker `@aaronjbecker <https://github.com/aaronjbecker>`_
8990
- Add "Name <email (optional)> and github profile link" above this line.

CHANGES.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Unreleased
99
**Added**
1010

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

1315
**Changed**
1416

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

2737
**Removed**
2838

praw/models/reddit/subreddit.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,22 +2889,27 @@ def _upload_media(
28892889
self,
28902890
*,
28912891
expected_mime_prefix: str | None = None,
2892-
media_path: str,
2892+
media_path: str | None,
28932893
upload_type: str = "link",
28942894
) -> str:
28952895
"""Upload media and return its URL and a websocket (Undocumented endpoint).
28962896
28972897
:param expected_mime_prefix: If provided, enforce that the media has a mime type
28982898
that starts with the provided prefix.
2899+
:param media_path: The path to the media file to upload. Default is the PRAW
2900+
logo.
28992901
:param upload_type: One of ``"link"``, ``"gallery"'', or ``"selfpost"``
29002902
(default: ``"link"``).
29012903
29022904
:returns: The link to the uploaded media.
29032905
29042906
"""
29052907
if media_path is None:
2906-
file = Path(__file__).absolute()
2907-
media_path = file.parent.parent.parent / "images" / "PRAW logo.png"
2908+
# if we're uploading without a media path, assume we're uploading a PRAW logo
2909+
# this default is commonly used when ``video_poster_url`` is not provided in ``submit_video``
2910+
module_path = Path(__file__).absolute()
2911+
logo_path = module_path.parent.parent.parent / "images" / "PRAW logo.png"
2912+
file = Path(logo_path)
29082913
else:
29092914
file = Path(media_path)
29102915

@@ -3073,12 +3078,14 @@ def submit(
30733078
this value will set a custom text (default: ``None``). ``flair_id`` is
30743079
required when ``flair_text`` is provided.
30753080
:param inline_media: A dict of :class:`.InlineMedia` objects where the key is
3076-
the placeholder name in ``selftext``.
3081+
the placeholder name in ``selftext``. Link post selftext does not support
3082+
inline media.
30773083
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
30783084
:param resubmit: When ``False``, an error will occur if the URL has already been
30793085
submitted (default: ``True``).
3080-
:param selftext: The Markdown formatted content for a ``text`` submission. Use
3081-
an empty string, ``""``, to make a title-only submission.
3086+
:param selftext: The Markdown formatted content for a ``text`` submission or an
3087+
optional post body for ``link`` submissions. Use an empty string, ``""``, to
3088+
make a title-only submission.
30823089
:param send_replies: When ``True``, messages will be sent to the submission
30833090
author when comments are made to the submission (default: ``True``).
30843091
:param spoiler: Whether the submission should be marked as a spoiler (default:
@@ -3087,7 +3094,10 @@ def submit(
30873094
30883095
:returns: A :class:`.Submission` object for the newly created submission.
30893096
3090-
Either ``selftext`` or ``url`` can be provided, but not both.
3097+
Provide ``selftext`` alone for a ``text`` submission. ``selftext`` can accompany
3098+
a ``url`` for a ``link`` submission. ``selftext`` that accompanies a ``link``
3099+
submission is optional. ``selftext`` for ``link`` submissions does not support
3100+
``inline_media``.
30913101
30923102
For example, to submit a URL to r/test do:
30933103
@@ -3152,8 +3162,10 @@ def submit(
31523162
- :meth:`~.Subreddit.submit_video` to submit videos and videogifs
31533163
31543164
"""
3155-
if (bool(selftext) or selftext == "") == bool(url): # noqa: PLC1901
3156-
msg = "Either 'selftext' or 'url' must be provided."
3165+
# link posts can now include selftext (no longer exclusive)
3166+
# test for empty string in selftext for title-only submissions
3167+
if not url and not (bool(selftext) or selftext == ""): # noqa: PLC1901
3168+
msg = "Submission requires either 'selftext' or 'url' to be provided."
31573169
raise TypeError(msg)
31583170

31593171
data = {
@@ -3174,7 +3186,15 @@ def submit(
31743186
):
31753187
if value is not None:
31763188
data[key] = value
3177-
if selftext is not None:
3189+
if url is not None:
3190+
data.update(kind="link", url=url)
3191+
if inline_media:
3192+
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."
3193+
raise TypeError(msg)
3194+
# we can ignore an empty string for selftext here b/c body text is optional for link posts
3195+
if selftext:
3196+
data.update(text=selftext)
3197+
elif selftext is not None:
31783198
data.update(kind="self")
31793199
if inline_media:
31803200
body = selftext.format(**{
@@ -3184,8 +3204,6 @@ def submit(
31843204
data.update(richtext_json=dumps(converted))
31853205
else:
31863206
data.update(text=selftext)
3187-
else:
3188-
data.update(kind="link", url=url)
31893207

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

@@ -3199,6 +3217,7 @@ def submit_gallery(
31993217
flair_id: str | None = None,
32003218
flair_text: str | None = None,
32013219
nsfw: bool = False,
3220+
selftext: str | None = None,
32023221
send_replies: bool = True,
32033222
spoiler: bool = False,
32043223
) -> praw.models.Submission:
@@ -3217,6 +3236,8 @@ def submit_gallery(
32173236
this value will set a custom text (default: ``None``). ``flair_id`` is
32183237
required when ``flair_text`` is provided.
32193238
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
3239+
:param selftext: Optional Markdown-formatted post body content (default:
3240+
``None``).
32203241
:param send_replies: When ``True``, messages will be sent to the submission
32213242
author when comments are made to the submission (default: ``True``).
32223243
:param spoiler: Whether the submission should be marked asa spoiler (default:
@@ -3274,6 +3295,7 @@ def submit_gallery(
32743295
("flair_text", flair_text),
32753296
("collection_id", collection_id),
32763297
("discussion_type", discussion_type),
3298+
("text", selftext),
32773299
):
32783300
if value is not None:
32793301
data[key] = value
@@ -3303,6 +3325,7 @@ def submit_image(
33033325
flair_text: str | None = None,
33043326
nsfw: bool = False,
33053327
resubmit: bool = True,
3328+
selftext: str | None = None,
33063329
send_replies: bool = True,
33073330
spoiler: bool = False,
33083331
timeout: int = 10,
@@ -3322,6 +3345,8 @@ def submit_image(
33223345
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
33233346
:param resubmit: When ``False``, an error will occur if the URL has already been
33243347
submitted (default: ``True``).
3348+
:param selftext: Optional Markdown-formatted post body content (default:
3349+
``None``).
33253350
:param send_replies: When ``True``, messages will be sent to the submission
33263351
author when comments are made to the submission (default: ``True``).
33273352
:param spoiler: Whether the submission should be marked as a spoiler (default:
@@ -3383,6 +3408,7 @@ def submit_image(
33833408
("flair_text", flair_text),
33843409
("collection_id", collection_id),
33853410
("discussion_type", discussion_type),
3411+
("text", selftext),
33863412
):
33873413
if value is not None:
33883414
data[key] = value
@@ -3485,6 +3511,7 @@ def submit_video(
34853511
flair_text: str | None = None,
34863512
nsfw: bool = False,
34873513
resubmit: bool = True,
3514+
selftext: str | None = None,
34883515
send_replies: bool = True,
34893516
spoiler: bool = False,
34903517
thumbnail_path: str | None = None,
@@ -3507,6 +3534,8 @@ def submit_video(
35073534
:param nsfw: Whether the submission should be marked NSFW (default: ``False``).
35083535
:param resubmit: When ``False``, an error will occur if the URL has already been
35093536
submitted (default: ``True``).
3537+
:param selftext: Optional Markdown-formatted post body content (default:
3538+
``None``).
35103539
:param send_replies: When ``True``, messages will be sent to the submission
35113540
author when comments are made to the submission (default: ``True``).
35123541
:param spoiler: Whether the submission should be marked as a spoiler (default:
@@ -3572,6 +3601,7 @@ def submit_video(
35723601
("flair_text", flair_text),
35733602
("collection_id", collection_id),
35743603
("discussion_type", discussion_type),
3604+
("text", selftext),
35753605
):
35763606
if value is not None:
35773607
data[key] = value

0 commit comments

Comments
 (0)