Skip to content

Commit

Permalink
Merge pull request #1130 from H4CKY54CK/master
Browse files Browse the repository at this point in the history
Added emoji permission support
  • Loading branch information
bboe committed Feb 10, 2020
2 parents d3a8a28 + bb0e00d commit 428ca8f
Show file tree
Hide file tree
Showing 12 changed files with 1,543 additions and 453 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Expand Up @@ -51,6 +51,7 @@ Source Contributors
- LilSpazJoekp `@LilSpazJoekp <https://github.com/LilSpazJoekp>`_
- Timendum `@timendum <https://github.com/timendum>`_
- vaclav-2012 `@vaclav-2012 <https://github.com/vaclav-2012>`_
- Jon Meager `@H4CKY54CK <https://github.com/H4CKY54CK>`_
- kungming2 `@kungming2 <https://github.com/kungming2>`_
- Jack Steel `@jackodsteel <https://github.com/jackodsteel>`_
- David Mirch `@fwump38 <https://github.com/fwump38>`_
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -17,6 +17,9 @@ Unreleased
friends with the user, otherwise throws an exception.
* :meth:`.SubmissionModeration.flair` has the parameter ``flair_template_id``
for applying flairs with template IDs.
* :meth:`~.Emoji.update` supports modifying an emoji's permissions.
* :meth:`~.SubredditEmoji.add` now supports optionally passing booleans to set
an emoji's permissions upon upload.

**Removed**

Expand Down
1 change: 1 addition & 0 deletions praw/endpoints.py
Expand Up @@ -46,6 +46,7 @@
"emoji_delete": "api/v1/{subreddit}/emoji/{emoji_name}",
"emoji_lease": "api/v1/{subreddit}/emoji_asset_upload_s3.json",
"emoji_list": "api/v1/{subreddit}/emojis/all",
"emoji_update": "api/v1/{subreddit}/emoji_permissions",
"emoji_upload": "api/v1/{subreddit}/emoji.json",
"flair": "r/{subreddit}/api/flair/",
"flairconfig": "r/{subreddit}/api/flairconfig/",
Expand Down
98 changes: 88 additions & 10 deletions praw/models/reddit/emoji.py
Expand Up @@ -25,9 +25,13 @@ class Emoji(RedditBase):
======================= ===================================================
Attribute Description
======================= ===================================================
``mod_flair_only`` Whether the emoji is restricted for mod use only.
``name`` The name of the emoji.
``post_flair_allowed`` Whether the emoji may appear in post flair.
``url`` The URL of the emoji image.
``user_flair_allowed`` Whether the emoji may appear in user flair.
======================= ===================================================
"""

STR_FIELD = "name"
Expand Down Expand Up @@ -89,6 +93,58 @@ def delete(self):
)
self._reddit.request("DELETE", url)

def update(
self,
mod_flair_only: Optional[bool] = None,
post_flair_allowed: Optional[bool] = None,
user_flair_allowed: Optional[bool] = None,
):
"""Update the permissions of an emoji in this subreddit.
:param mod_flair_only: (boolean) Indicate whether the emoji is
restricted to mod use only. Respects pre-existing settings if not
provided.
:param post_flair_allowed: (boolean) Indicate whether the emoji may
appear in post flair. Respects pre-existing settings if not
provided.
:param user_flair_allowed: (boolean) Indicate whether the emoji may
appear in user flair. Respects pre-existing settings if not
provided.
.. note:: In order to retain pre-existing values for those that are not
explicitly passed, a network request is issued. To avoid that
network request, explicitly provide all values.
To restrict the emoji ``test`` in subreddit ``wowemoji`` to mod use
only, try:
.. code-block:: python
reddit.subreddit("wowemoji").emoji["test"].update(mod_flair_only=True)
"""
locals_reference = locals()
mapping = {
attribute: locals_reference[attribute]
for attribute in (
"mod_flair_only",
"post_flair_allowed",
"user_flair_allowed",
)
}
if all(value is None for value in mapping.values()):
raise TypeError("At least one attribute must be provided")

data = {"name": self.name}
for attribute, value in mapping.items():
if value is None:
value = getattr(self, attribute)
data[attribute] = value
url = API_PATH["emoji_update"].format(subreddit=self.subreddit)
self._reddit.post(url, data=data)
for attribute, value in data.items():
setattr(self, attribute, value)


class SubredditEmoji:
"""Provides a set of functions to a Subreddit for emoji."""
Expand Down Expand Up @@ -128,28 +184,45 @@ def __iter__(self) -> List[Emoji]:
print(emoji)
"""
response = self.subreddit._reddit.get(
response = self._reddit.get(
API_PATH["emoji_list"].format(subreddit=self.subreddit)
)
for emoji_name, emoji_data in response[
self.subreddit.fullname
].items():
subreddit_keys = [
key
for key in response.keys()
if key.startswith(self._reddit.config.kinds["subreddit"])
]
assert len(subreddit_keys) == 1
for emoji_name, emoji_data in response[subreddit_keys[0]].items():
yield Emoji(
self._reddit, self.subreddit, emoji_name, _data=emoji_data
)

def add(self, name: str, image_path: str):
def add(
self,
name: str,
image_path: str,
mod_flair_only: Optional[bool] = None,
post_flair_allowed: Optional[bool] = None,
user_flair_allowed: Optional[bool] = None,
) -> Emoji:
"""Add an emoji to this subreddit.
:param name: The name of the emoji
:param image_path: A path to a jpeg or png image.
:param mod_flair_only: (boolean) When provided, indicate whether the
emoji is restricted to mod use only. (Default: ``None``)
:param post_flair_allowed: (boolean) When provided, indicate whether
the emoji may appear in post flair. (Default: ``None``)
:param user_flair_allowed: (boolean) When provided, indicate whether
the emoji may appear in user flair. (Default: ``None``)
:returns: The Emoji added.
To add ``'test'`` to the subreddit ``'praw_test'`` try:
To add ``test`` to the subreddit ``praw_test`` try:
.. code-block:: python
reddit.subreddit('praw_test').emoji.add('test','test.png')
reddit.subreddit("praw_test").emoji.add("test", "test.png")
"""
data = {
Expand All @@ -173,8 +246,13 @@ def add(self, name: str, image_path: str):
)
response.raise_for_status()

data = {
"mod_flair_only": mod_flair_only,
"name": name,
"post_flair_allowed": post_flair_allowed,
"s3_key": upload_data["key"],
"user_flair_allowed": user_flair_allowed,
}
url = API_PATH["emoji_upload"].format(subreddit=self.subreddit)
self._reddit.post(
url, data={"name": name, "s3_key": upload_data["key"]}
)
self._reddit.post(url, data=data)
return Emoji(self._reddit, self.subreddit, name)
168 changes: 26 additions & 142 deletions tests/integration/cassettes/TestEmoji.test__fetch.json

Large diffs are not rendered by default.

202 changes: 43 additions & 159 deletions tests/integration/cassettes/TestEmoji.test__fetch__invalid_emoji.json

Large diffs are not rendered by default.

223 changes: 223 additions & 0 deletions tests/integration/cassettes/TestEmoji.test_update.json
@@ -0,0 +1,223 @@
{
"http_interactions": [
{
"recorded_at": "2020-02-08T08:37:36",
"request": {
"body": {
"encoding": "utf-8",
"string": "grant_type=password&password=<PASSWORD>&username=<USERNAME>"
},
"headers": {
"Accept": [
"*/*"
],
"Accept-Encoding": [
"identity"
],
"Authorization": [
"Basic <BASIC_AUTH>"
],
"Connection": [
"keep-alive"
],
"Content-Length": [
"59"
],
"Content-Type": [
"application/x-www-form-urlencoded"
],
"User-Agent": [
"<USER_AGENT> PRAW/7.0.0.dev0 prawcore/1.0.1"
]
},
"method": "POST",
"uri": "https://www.reddit.com/api/v1/access_token"
},
"response": {
"body": {
"encoding": "UTF-8",
"string": "{\"access_token\": \"<ACCESS_TOKEN>\", \"token_type\": \"bearer\", \"expires_in\": 3600, \"scope\": \"*\"}"
},
"headers": {
"Accept-Ranges": [
"bytes"
],
"Connection": [
"keep-alive"
],
"Content-Length": [
"113"
],
"Content-Type": [
"application/json; charset=UTF-8"
],
"Date": [
"Sat, 08 Feb 2020 08:37:36 GMT"
],
"Server": [
"snooserv"
],
"Set-Cookie": [
"edgebucket=u8Hc26P8bvtRks1HfM; Domain=reddit.com; Max-Age=63071999; Path=/; secure"
],
"Strict-Transport-Security": [
"max-age=15552000; includeSubDomains; preload"
],
"Via": [
"1.1 varnish"
],
"X-Cache": [
"MISS"
],
"X-Cache-Hits": [
"0"
],
"X-Moose": [
"majestic"
],
"X-Served-By": [
"cache-lax8639-LAX"
],
"X-Timer": [
"S1581151056.258717,VS0,VE357"
],
"cache-control": [
"max-age=0, must-revalidate"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"1; mode=block"
]
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://www.reddit.com/api/v1/access_token"
}
},
{
"recorded_at": "2020-02-08T08:37:36",
"request": {
"body": {
"encoding": "utf-8",
"string": "api_type=json&mod_flair_only=False&name=test_png&post_flair_allowed=True&user_flair_allowed=True"
},
"headers": {
"Accept": [
"*/*"
],
"Accept-Encoding": [
"identity"
],
"Authorization": [
"bearer <ACCESS_TOKEN>"
],
"Connection": [
"keep-alive"
],
"Content-Length": [
"96"
],
"Content-Type": [
"application/x-www-form-urlencoded"
],
"Cookie": [
"edgebucket=u8Hc26P8bvtRks1HfM"
],
"User-Agent": [
"<USER_AGENT> PRAW/7.0.0.dev0 prawcore/1.0.1"
]
},
"method": "POST",
"uri": "https://oauth.reddit.com/api/v1/<TEST_SUBREDDIT>/emoji_permissions?raw_json=1"
},
"response": {
"body": {
"encoding": "UTF-8",
"string": "{\"json\": {\"errors\": []}}"
},
"headers": {
"Accept-Ranges": [
"bytes"
],
"Connection": [
"keep-alive"
],
"Content-Length": [
"24"
],
"Content-Type": [
"application/json; charset=UTF-8"
],
"Date": [
"Sat, 08 Feb 2020 08:37:36 GMT"
],
"Server": [
"snooserv"
],
"Strict-Transport-Security": [
"max-age=15552000; includeSubDomains; preload"
],
"Via": [
"1.1 varnish"
],
"X-Cache": [
"MISS"
],
"X-Cache-Hits": [
"0"
],
"X-Moose": [
"majestic"
],
"X-Served-By": [
"cache-lax8637-LAX"
],
"X-Timer": [
"S1581151057.828026,VS0,VE104"
],
"cache-control": [
"private, s-maxage=0, max-age=0, must-revalidate, no-store, max-age=0, must-revalidate"
],
"expires": [
"-1"
],
"set-cookie": [
"loid=00000000000004cixf.2.1284611485984.Z0FBQUFBQmVQbk5RVWR0QU41RjNtRDRpNk5Db3NOZXVkeUZqZ1lwUU1WSXBFekNEWmQwMFBFVzdvRThMWFFnbVZxMUxGTnBsblA5NHJZbWZ4QXBmSWU1OXhhTFNfR0VnbVIwaEZ4N3ZQWWxxNFFSQ0RfdmxNR2pGV3pqaTlNd0UwRFhNUVRWbTNXcUo; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Mon, 07-Feb-2022 08:37:36 GMT; secure",
"session_tracker=F7MrXfFASxwroLmGSB.0.1581151056883.Z0FBQUFBQmVQbk5RYTdBMXNJbXh6Mk8wQV9hTU9nQ281UVRfTTFFdlF4T3IxazgwcS03OVoyOUwydUpkU1dGd3VoTzUzd3BkeTYtTUFNdXlCT01rRDFHWWJLRmZ0WGJ1S3VOcE5na3E2Ym5MeGVLZkRfQnJMaHd5Z2RucXJFR2RxT2Y1NVhlM1JfVzI; Domain=reddit.com; Max-Age=7199; Path=/; expires=Sat, 08-Feb-2020 10:37:36 GMT; secure"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-ratelimit-remaining": [
"599.0"
],
"x-ratelimit-reset": [
"144"
],
"x-ratelimit-used": [
"1"
],
"x-xss-protection": [
"1; mode=block"
]
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://oauth.reddit.com/api/v1/<TEST_SUBREDDIT>/emoji_permissions?raw_json=1"
}
}
],
"recorded_with": "betamax/0.8.1"
}

0 comments on commit 428ca8f

Please sign in to comment.