Skip to content

Commit a460e7e

Browse files
authored
Merge pull request #1764 from MaybeNetwork/moderator-subreddits
Restore User.moderator_subreddits
2 parents fdc8a29 + 1bceed3 commit a460e7e

File tree

5 files changed

+288
-1
lines changed

5 files changed

+288
-1
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Unreleased
1414
- :meth:`.Inbox.mark_all_read` to mark all messages as read with one API call.
1515
- :meth:`~.InboxableMixin.unblock_subreddit` to unblock a subreddit.
1616
- :meth:`.update_crowd_control_level` to update the crowd control level of a post.
17+
- :meth:`.moderator_subreddits`, which returns information about the subreddits that the
18+
authenticated user moderates, has been restored.
1719

1820
7.3.0 (2021/06/17)
1921
------------------

praw/models/reddit/redditor.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ def moderated(self) -> List["praw.models.Subreddit"]:
280280
:returns: A ``list`` of :class:`~.Subreddit` objects. Return ``[]`` if the
281281
redditor has no moderated subreddits.
282282
283+
:raises: ``prawcore.ServerError`` in certain cicumstances. See the note below.
284+
283285
.. note::
284286
285287
The redditor's own user profile subreddit will not be returned, but other
@@ -293,6 +295,29 @@ def moderated(self) -> List["praw.models.Subreddit"]:
293295
print(subreddit.display_name)
294296
print(subreddit.title)
295297
298+
.. note::
299+
300+
A ``prawcore.ServerError`` exception may be raised if the redditor moderates
301+
a large number of subreddits. If that happens, try switching to
302+
:ref:`read-only mode <read_only_application>`. For example,
303+
304+
.. code-block:: python
305+
306+
reddit.read_only = True
307+
for subreddit in reddit.redditor("reddit").moderated():
308+
print(str(subreddit))
309+
310+
It is possible that requests made in read-only mode will also raise a
311+
``prawcore.ServerError`` exception.
312+
313+
When used in read-only mode, this method does not retrieve information about
314+
subreddits that require certain special permissions to access, e.g., private
315+
subreddits and premium-only subreddits.
316+
317+
.. seealso::
318+
319+
:meth:`.User.moderator_subreddits`
320+
296321
"""
297322
return self._reddit.get(API_PATH["moderated"].format(user=self)) or []
298323

praw/models/user.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,18 @@ def contributor_subreddits(
6565
) -> Iterator["praw.models.Subreddit"]:
6666
"""Return a :class:`.ListingGenerator` of contributor subreddits.
6767
68-
These are subreddits that the user is a contributor of.
68+
These are subreddits in which the user is an approved user.
6969
7070
Additional keyword arguments are passed in the initialization of
7171
:class:`.ListingGenerator`.
7272
73+
To print a list of the subreddits that you are an approved user in, try:
74+
75+
.. code-block:: python
76+
77+
for subreddit in reddit.user.contributor_subreddits(limit=None):
78+
print(str(subreddit))
79+
7380
"""
7481
return ListingGenerator(
7582
self._reddit, API_PATH["my_contributor"], **generator_kwargs
@@ -156,6 +163,30 @@ def me(
156163
self._me = Redditor(self._reddit, _data=user_data)
157164
return self._me
158165

166+
def moderator_subreddits(
167+
self, **generator_kwargs: Union[str, int, Dict[str, str]]
168+
) -> Iterator["praw.models.Subreddit"]:
169+
"""Return a :class:`.ListingGenerator` subreddits that the user moderates.
170+
171+
Additional keyword arguments are passed in the initialization of
172+
:class:`.ListingGenerator`.
173+
174+
To print a list of the names of the subreddits you moderate, try:
175+
176+
.. code-block:: python
177+
178+
for subreddit in reddit.user.moderator_subreddits(limit=None):
179+
print(str(subreddit))
180+
181+
.. seealso::
182+
183+
:meth:`.Redditor.moderated`
184+
185+
"""
186+
return ListingGenerator(
187+
self._reddit, API_PATH["my_moderator"], **generator_kwargs
188+
)
189+
159190
def multireddits(self) -> List["praw.models.Multireddit"]:
160191
"""Return a list of multireddits belonging to the user."""
161192
return self._reddit.get(API_PATH["my_multireddits"])
@@ -168,6 +199,13 @@ def subreddits(
168199
Additional keyword arguments are passed in the initialization of
169200
:class:`.ListingGenerator`.
170201
202+
To print a list of the subreddits that you are subscribed to, try:
203+
204+
.. code-block:: python
205+
206+
for subreddit in reddit.user.subreddits(limit=None):
207+
print(str(subreddit))
208+
171209
"""
172210
return ListingGenerator(
173211
self._reddit, API_PATH["my_subreddits"], **generator_kwargs
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
{
2+
"http_interactions": [
3+
{
4+
"recorded_at": "2021-07-14T07:47:34",
5+
"request": {
6+
"body": {
7+
"encoding": "utf-8",
8+
"string": "grant_type=password&password=<PASSWORD>&username=<USERNAME>"
9+
},
10+
"headers": {
11+
"Accept": [
12+
"*/*"
13+
],
14+
"Accept-Encoding": [
15+
"identity"
16+
],
17+
"Authorization": [
18+
"Basic <BASIC_AUTH>"
19+
],
20+
"Connection": [
21+
"close"
22+
],
23+
"Content-Length": [
24+
"152"
25+
],
26+
"Content-Type": [
27+
"application/x-www-form-urlencoded"
28+
],
29+
"User-Agent": [
30+
"<USER_AGENT> PRAW/7.3.1.dev0 prawcore/2.2.0"
31+
]
32+
},
33+
"method": "POST",
34+
"uri": "https://www.reddit.com/api/v1/access_token"
35+
},
36+
"response": {
37+
"body": {
38+
"encoding": "UTF-8",
39+
"string": "{\"access_token\": \"<ACCESS_TOKEN>\", \"token_type\": \"bearer\", \"expires_in\": 3600, \"scope\": \"*\"}"
40+
},
41+
"headers": {
42+
"Accept-Ranges": [
43+
"bytes"
44+
],
45+
"Connection": [
46+
"close"
47+
],
48+
"Content-Length": [
49+
"121"
50+
],
51+
"Content-Type": [
52+
"application/json; charset=UTF-8"
53+
],
54+
"Date": [
55+
"Wed, 14 Jul 2021 07:47:35 GMT"
56+
],
57+
"Server": [
58+
"snooserv"
59+
],
60+
"Set-Cookie": [
61+
"edgebucket=iOZVqzcxgFvwiPreMf; Domain=reddit.com; Max-Age=63071999; Path=/; secure"
62+
],
63+
"Strict-Transport-Security": [
64+
"max-age=15552000; includeSubDomains; preload"
65+
],
66+
"Via": [
67+
"1.1 varnish"
68+
],
69+
"X-Clacks-Overhead": [
70+
"GNU Terry Pratchett"
71+
],
72+
"X-Moose": [
73+
"majestic"
74+
],
75+
"cache-control": [
76+
"max-age=0, must-revalidate"
77+
],
78+
"x-content-type-options": [
79+
"nosniff"
80+
],
81+
"x-frame-options": [
82+
"SAMEORIGIN"
83+
],
84+
"x-ratelimit-remaining": [
85+
"299"
86+
],
87+
"x-ratelimit-reset": [
88+
"145"
89+
],
90+
"x-ratelimit-used": [
91+
"1"
92+
],
93+
"x-xss-protection": [
94+
"1; mode=block"
95+
]
96+
},
97+
"status": {
98+
"code": 200,
99+
"message": "OK"
100+
},
101+
"url": "https://www.reddit.com/api/v1/access_token"
102+
}
103+
},
104+
{
105+
"recorded_at": "2021-07-14T07:47:34",
106+
"request": {
107+
"body": {
108+
"encoding": "utf-8",
109+
"string": ""
110+
},
111+
"headers": {
112+
"Accept": [
113+
"*/*"
114+
],
115+
"Accept-Encoding": [
116+
"identity"
117+
],
118+
"Authorization": [
119+
"bearer <ACCESS_TOKEN>"
120+
],
121+
"Connection": [
122+
"keep-alive"
123+
],
124+
"Cookie": [
125+
"edgebucket=iOZVqzcxgFvwiPreMf"
126+
],
127+
"User-Agent": [
128+
"<USER_AGENT> PRAW/7.3.1.dev0 prawcore/2.2.0"
129+
]
130+
},
131+
"method": "GET",
132+
"uri": "https://oauth.reddit.com/subreddits/mine/moderator/?limit=1024&raw_json=1"
133+
},
134+
"response": {
135+
"body": {
136+
"encoding": "UTF-8",
137+
"string": "{\"kind\": \"Listing\", \"data\": {\"after\": null, \"dist\": 2, \"modhash\": null, \"geo_filter\": \"\", \"children\": [{\"kind\": \"t5\", \"data\": {\"user_flair_background_color\": null, \"submit_text_html\": null, \"restrict_posting\": true, \"user_is_banned\": false, \"free_form_reports\": true, \"wiki_enabled\": true, \"user_is_muted\": false, \"user_can_flair_in_sr\": null, \"display_name\": \"<TEST_SUBREDDIT>\", \"header_img\": null, \"title\": \"<TEST_SUBREDDIT>\", \"allow_galleries\": true, \"icon_size\": null, \"primary_color\": \"\", \"active_user_count\": null, \"icon_img\": \"\", \"display_name_prefixed\": \"r/<TEST_SUBREDDIT>\", \"accounts_active\": null, \"public_traffic\": false, \"subscribers\": 3, \"user_flair_richtext\": [], \"name\": \"t5_1111\", \"quarantine\": false, \"hide_ads\": false, \"prediction_leaderboard_entry_type\": \"IN_FEED\", \"emojis_enabled\": true, \"advertiser_category\": \"\", \"public_description\": \"\", \"comment_score_hide_mins\": 0, \"allow_predictions\": false, \"user_has_favorited\": false, \"user_flair_template_id\": null, \"community_icon\": \"\", \"banner_background_image\": \"\", \"original_content_tag_enabled\": false, \"community_reviewed\": false, \"submit_text\": \"\", \"description_html\": null, \"spoilers_enabled\": true, \"header_title\": \"\", \"header_size\": null, \"user_flair_position\": \"right\", \"all_original_content\": false, \"has_menu_widget\": false, \"is_enrolled_in_new_modmail\": true, \"key_color\": \"\", \"event_posts_enabled\": true, \"can_assign_user_flair\": false, \"created\": 1600000000.0, \"wls\": null, \"mod_permissions\": [], \"show_media_preview\": true, \"submission_type\": \"any\", \"user_is_subscriber\": true, \"disable_contributor_requests\": true, \"allow_videogifs\": true, \"user_flair_type\": \"text\", \"allow_polls\": false, \"collapse_deleted_comments\": false, \"emojis_custom_size\": null, \"public_description_html\": null, \"allow_videos\": false, \"is_crosspostable_subreddit\": true, \"notification_level\": null, \"can_assign_link_flair\": false, \"accounts_active_is_fuzzed\": false, \"submit_text_label\": \"\", \"link_flair_position\": \"\", \"user_sr_flair_enabled\": null, \"user_flair_enabled_in_sr\": false, \"allow_chat_post_creation\": true, \"allow_discovery\": false, \"user_sr_theme_enabled\": true, \"link_flair_enabled\": false, \"subreddit_type\": \"public\", \"suggested_comment_sort\": null, \"banner_img\": \"\", \"user_flair_text\": null, \"banner_background_color\": \"\", \"show_media\": true, \"id\": \"1111\", \"user_is_moderator\": true, \"over18\": false, \"description\": \"\", \"is_chat_post_feature_enabled\": true, \"submit_link_label\": \"\", \"user_flair_text_color\": null, \"restrict_commenting\": false, \"user_flair_css_class\": null, \"allow_images\": true, \"lang\": \"en\", \"whitelist_status\": null, \"url\": \"/r/<TEST_SUBREDDIT>/\", \"created_utc\": 1600000000.0, \"banner_size\": null, \"mobile_banner_image\": \"\", \"user_is_contributor\": false, \"allow_predictions_tournament\": false}}, {\"kind\": \"t5\", \"data\": {\"user_flair_background_color\": null, \"submit_text_html\": null, \"restrict_posting\": true, \"user_flair_enabled_in_sr\": false, \"user_is_banned\": false, \"free_form_reports\": true, \"wiki_enabled\": true, \"user_is_muted\": false, \"user_can_flair_in_sr\": null, \"display_name\": \"u_<USERNAME>\", \"header_img\": null, \"title\": \"\", \"allow_galleries\": true, \"icon_size\": [256, 256], \"primary_color\": \"\", \"active_user_count\": null, \"icon_img\": \"https://www.redditstatic.com/avatars/avatar_default_11_FF4500.png\", \"display_name_prefixed\": \"u/<USERNAME>\", \"accounts_active\": null, \"public_traffic\": false, \"subscribers\": 2, \"user_flair_richtext\": [], \"videostream_links_count\": 0, \"name\": \"t5_1112\", \"quarantine\": false, \"hide_ads\": false, \"prediction_leaderboard_entry_type\": \"IN_FEED\", \"emojis_enabled\": false, \"advertiser_category\": \"\", \"public_description\": \"\", \"comment_score_hide_mins\": 0, \"allow_predictions\": false, \"user_has_favorited\": false, \"user_flair_template_id\": null, \"community_icon\": \"\", \"banner_background_image\": \"\", \"original_content_tag_enabled\": false, \"community_reviewed\": false, \"submit_text\": \"\", \"description_html\": null, \"spoilers_enabled\": true, \"header_title\": \"\", \"header_size\": null, \"user_flair_position\": \"right\", \"is_default_icon\": [true], \"all_original_content\": false, \"collections_enabled\": true, \"is_enrolled_in_new_modmail\": true, \"key_color\": \"\", \"event_posts_enabled\": true, \"can_assign_user_flair\": false, \"created\": 1600000000.0, \"wls\": null, \"mod_permissions\": [\"all\"], \"show_media_preview\": true, \"submission_type\": \"any\", \"user_is_subscriber\": false, \"disable_contributor_requests\": false, \"allow_videogifs\": true, \"user_flair_type\": \"text\", \"allow_polls\": true, \"collapse_deleted_comments\": true, \"coins\": 0, \"emojis_custom_size\": null, \"public_description_html\": null, \"allow_videos\": true, \"is_crosspostable_subreddit\": true, \"notification_level\": null, \"can_assign_link_flair\": false, \"has_menu_widget\": false, \"accounts_active_is_fuzzed\": false, \"submit_text_label\": \"\", \"link_flair_position\": \"\", \"user_sr_flair_enabled\": null, \"is_default_banner\": true, \"allow_discovery\": true, \"user_sr_theme_enabled\": true, \"link_flair_enabled\": false, \"subreddit_type\": \"user\", \"suggested_comment_sort\": \"qa\", \"banner_img\": \"\", \"user_flair_text\": null, \"banner_background_color\": \"\", \"show_media\": true, \"id\": \"1112\", \"user_is_moderator\": true, \"over18\": false, \"description\": \"\", \"submit_link_label\": \"\", \"user_flair_text_color\": null, \"restrict_commenting\": false, \"user_flair_css_class\": null, \"allow_images\": true, \"lang\": \"en\", \"whitelist_status\": null, \"url\": \"/user/<USERNAME>/\", \"created_utc\": 1600000000.0, \"banner_size\": null, \"mobile_banner_image\": \"\", \"user_is_contributor\": false, \"allow_predictions_tournament\": false}}], \"before\": null}}"
138+
},
139+
"headers": {
140+
"Accept-Ranges": [
141+
"bytes"
142+
],
143+
"Connection": [
144+
"keep-alive"
145+
],
146+
"Content-Length": [
147+
"5579"
148+
],
149+
"Content-Type": [
150+
"application/json; charset=UTF-8"
151+
],
152+
"Date": [
153+
"Wed, 14 Jul 2021 07:47:35 GMT"
154+
],
155+
"Server": [
156+
"snooserv"
157+
],
158+
"Set-Cookie": [
159+
"session_tracker=iczchyyganqajsdxrm.0.1626248855536.Z0FBQUFBQmc3pGFYYzA0bFpXcEcwYnpPS19BeTVEUlFqaUtvOWpjNnB1TFh4bVMxV2p2VGNENlN9eGZCcXdJSjZZLVJ5WE9kMElhR6ZTdzRoSWIxcU1OUEozpVBrX1B4YjNPNE9SarRXeDdTSzRqZlYwcXVmOXVOOExuNkdOZHdiOTZudUhIVmJnNUw; Domain=reddit.com; Max-Age=7199; Path=/; expires=Wed, 14-Jul-2021 09:47:35 GMT; secure; SameSite=None; Secure",
160+
"csv=1; Max-Age=63072000; Domain=.reddit.com; Path=/; Secure; SameSite=None"
161+
],
162+
"Strict-Transport-Security": [
163+
"max-age=15552000; includeSubDomains; preload"
164+
],
165+
"Vary": [
166+
"accept-encoding"
167+
],
168+
"Via": [
169+
"1.1 varnish"
170+
],
171+
"X-Clacks-Overhead": [
172+
"GNU Terry Pratchett"
173+
],
174+
"X-Moose": [
175+
"majestic"
176+
],
177+
"cache-control": [
178+
"private, s-maxage=0, max-age=0, must-revalidate, no-store, max-age=0, must-revalidate"
179+
],
180+
"expires": [
181+
"-1"
182+
],
183+
"x-content-type-options": [
184+
"nosniff"
185+
],
186+
"x-frame-options": [
187+
"SAMEORIGIN"
188+
],
189+
"x-ratelimit-remaining": [
190+
"599.0"
191+
],
192+
"x-ratelimit-reset": [
193+
"145"
194+
],
195+
"x-ratelimit-used": [
196+
"1"
197+
],
198+
"x-ua-compatible": [
199+
"IE=edge"
200+
],
201+
"x-xss-protection": [
202+
"1; mode=block"
203+
]
204+
},
205+
"status": {
206+
"code": 200,
207+
"message": "OK"
208+
},
209+
"url": "https://oauth.reddit.com/subreddits/mine/moderator/?limit=1024&raw_json=1"
210+
}
211+
}
212+
],
213+
"recorded_with": "betamax/0.8.1"
214+
}

tests/integration/models/test_user.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ def test_me__bypass_cache(self, _):
8080
me.praw_is_cached = True
8181
assert not hasattr(self.reddit.user.me(use_cache=False), "praw_is_cached")
8282

83+
@mock.patch("time.sleep", return_value=None)
84+
def test_moderator_subreddits(self, _):
85+
self.reddit.read_only = False
86+
with self.recorder.use_cassette("TestUser.test_moderator_subreddits"):
87+
mod_subs = list(self.reddit.user.moderator_subreddits(limit=None))
88+
assert mod_subs
89+
assert all(isinstance(x, Subreddit) for x in mod_subs)
90+
8391
def test_multireddits(self):
8492
self.reddit.read_only = False
8593
with self.use_cassette():

0 commit comments

Comments
 (0)