Coming soon - Get a detailed view of why an account is flagged as spam!
view details

This post has been de-listed

It is no longer included in search results and normal feeds (front page, hot posts, subreddit posts, etc). It remains visible only via the author's post history.

2
RedditWarp v1.1 release
Post Body


RedditWarp version 1.1 has just been released.

RedditWarp is a fully type annotated Python API wrapper for Reddit.

In this post we will go through some of the highlights of the changes. See the change log file in the repository for a fuller list of changes.

TL;DR: In this release, configuring post flairs’ post appearance is now supported; API procedures now accept base-36 string IDs; and a powerful new feature called ‘middleware injection’ has been implemented.


New API procedure: configure post flair post appearance

The ability to configure a post flair’s post appearance has been added. Credit to u/Then_Marionberry_259 for raising this question in r/redditdev.

To set a background image on posts with a particular post flair, use code like the following.

from io import BytesIO
from mimetypes import guess_extension

import redditwarp.SYNC

client = redditwarp.SYNC.Client.from_praw_config('Pyprohly')

subreddit = 'Pyprohly_test3'
post_flair_uuid = 'eeabd02a-af76-11ed-bfea-aaa3af62397b'
title_color = "#C0C0C0"
image_url = "https://placekitten.com/g/864/121"

resp = client.http.request('GET', image_url)
ext = guess_extension(resp.headers['content-type']) or '.jpeg'
filename = 'file'   ext
file = BytesIO(resp.data)
with file:
    lease = client.p.flair.post_appearance.upload_background(
        file,
        sr=subreddit,
        uuid=post_flair_uuid,
        filepath=filename,
    )

client.p.flair.post_appearance.config(
    subreddit,
    post_flair_uuid,
    title_color=title_color,
    background_image_url=lease.location,
)

When testing this feature, I noticed that the post appearances don’t show when using the dark theme of the web UI, except for the custom icon image. Be sure to turn off dark mode to see the changes.

API procedures now accept string IDs

The API procedures have been overloaded to accept string IDs in addition to integer IDs.

So you no longer have to write int(x, 36) so much.

client.p.submission.fetch(int('10gudzi', 36))
# <== Functionally identical ==>
client.p.submission.fetch('10gudzi')

Accompanying this change, model objects having id36 now have an idn attribute to access the integer ID, and this is preferred over id which is considered deprecated.

Renamed submission creation API procedures

The string ID support is part of a larger change in RedditWarp making it more impartial to integer IDs. One of the challenges in making this change was figuring out what to do with the submission creation methods, like client.p.submission.create_*_post(), that return integer IDs.

Since changing the return type of the client.p.submission.create_*_post() methods is a breaking change, I decided to add new methods like client.p.submission.create.*() instead. These new methods take a generic type parameter that allows you select the overload with the right return type for your uses.

# Functionally identical.
idn: int = client.p.submission.create_text_post('test', 'title', 'body')
idn: int = client.p.submission.create.text[int]('test', 'title', 'body')

# Return a string ID instead.
id36: str = client.p.submission.create.text[str]('test', 'title', 'body')

# No return value.
client.p.submission.create.text('test', 'title', 'body')

Middleware injection

A cool new feature has landed called ‘middleware injection’. It allows you to easily add temporary request handlers to the HTTP client request handler pipeline. This is a useful concept because can be used to essentially rewrite API procedures ‘on the spot’ without having to reimplement them.

The feature is accessible through client.http.having_additional_middleware() and is used like so:

import redditwarp.SYNC
from redditwarp.http.misc.apply_params_and_headers_SYNC import ApplyParams

client = redditwarp.SYNC.Client.from_praw_config('Pyprohly')

with client.http.having_additional_middleware(lambda h: ApplyParams(h, {'my_param': '12345'})):
    client.p.ping()

print(client.http.last.requisition_queue[-1].params)
# ~> {'scopes': 'read', 'my_param': '12345', 'raw_json': '1', 'api_type': 'json'}

The most common use case for this feature is to add support for unimplemented parameters to API procedures.

For example, for the submission creation endpoint, there is actually a special parameter called ad which RedditWarp nor PRAW directly support through its high-level API procedure methods. When true, this ad parameter creates an unlisted submission, only accessible by permalink.

Here’s how we can use middleware injection to create an unlisted submission to r/test:

import redditwarp.SYNC
from redditwarp.http.misc.apply_params_and_headers_SYNC import ApplyParams

client = redditwarp.SYNC.Client.from_praw_config('PyprohlyTest')

with client.http.having_additional_middleware(lambda h: ApplyParams(h, {'ad': '1'})):
    id36 = client.p.submission.create.text[str]('test', 'title', 'body')

subm = client.p.submission.fetch(id36)
print(subm.permalink)

I thought about adding this feature in for v1.0 but I wanted to see a legit use case for it before implementing it. The thing that motivated me to add it was u/LeMushroomScoop’s question here where he asks, in passing, how to get the ‘pfp’, which I assume stands for ‘profile pic’, when traversing a comment tree.

That’s a good question on its own. How does, for instance, the Reddit mobile client know how to get the user’s profile display picture when the comment resource data doesn’t seem to include it? The answer is that it sends a secret profile_img parameter during comment tree endpoint calls which populates the comment objects with a profile_img attribute containing the link to the comment author’s profile picture image.

We can obtain users’ profile pictures while traversing comment trees like so:

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from collections.abc import Iterator
    from redditwarp.models.comment_tree_SYNC import CommentSubtreeTreeNode

import redditwarp.SYNC
from redditwarp.models.comment_SYNC import Comment
from redditwarp.http.misc.apply_params_and_headers_SYNC import ApplyParams

def traversal(node: CommentSubtreeTreeNode[object]) -> Iterator[tuple[int, Comment]]:
    def traverse(root: CommentSubtreeTreeNode[object], level: int = 0) -> Iterator[tuple[int, Comment]]:
        value = root.value
        if isinstance(value, Comment):
            yield (level, value)

        for child in root.children:
            yield from traverse(child, level   1)

        if root.more:
            yield from traverse(root.more(), level)

    return traverse(node)

client = redditwarp.SYNC.Client()

with client.http.having_additional_middleware(lambda h: ApplyParams(h, {'profile_img': '1'})):
    tree_node = client.p.comment_tree.fetch('12ldtgq')
    for depth, c in traversal(tree_node):
        print(f"{depth*'.'} u/{c.author_display_name} | {c.d.get('profile_img')}")

Modmail stream bug fixed

While attempting to help u/key_equivalent0 with their modmail streaming question, I noticed there was a subtle but significant bug with RedditWarp’s modmail streaming logic wherein old conversation messages could theoretically be repeated in the stream if a conversation thread had lots of activity.

The way entries are added to modmail listings is actually a little different to other listings, because with modmail listings, older entries could be removed and moved to the top. Having not accounted for this, this meant that if one conversation thread had a lot of activity and got lots of messages, the stream’s memory could become saturated with expired entries and thus forget about other the conversations it has already seen and eventually start to repeat messages.

Modmail streams output a tuple of modmail conversations and their most recent message. The streaming mechanism remembers the entries by storing a tuple of the conversation ID and the message ID.

For example, say we have this in the stream’s memory:

(1, 10)
(2, 20)
(3, 30)

Let’s say conversation 2 got a new message 21. The listing would not look like this:

(2, 21)
(1, 10)
(2, 20)
(3, 30)

But instead look like:

(2, 21)
(1, 10)
(3, 30)

So the entry with conversation ID 2 was moved to the top and has a new message ID of 21. The previous faulty stream logic was still storing the entry (2, 20) in its memory, taking up space (in its capacity of 2000). So you can imagine how the stream’s memory could become saturated with a bunch of entries that no longer exist if there were a particular conversation thread that was very active.

While PRAW doesn’t share this bug, PRAW doesn’t support streaming modmail messages, only modmail conversations.


Thanks for reading.

Please join the RedditWarp Discord :)

Author
Account Strength
90%
Account Age
7 years
Verified Email
Yes
Verified Flair
No
Total Karma
3,030
Link Karma
92
Comment Karma
1,270
Profile updated: 5 days ago
RedditWarp Author

Subreddit

Post Details

We try to extract some basic information from the post title. This is not always successful or accurate, please use your best judgement and compare these values to the post title and body for confirmation.
Posted
1 year ago