Closed dequeued0 closed 4 years ago
It's much easier to embed the files as code:
testing account (normal account, not in friends): dequeued
2020-01-01T01:17:30 | INFO | test_user | getting user object succeeded for /u/dequeued
dequeued is friend? False
testing account (normal account, in friends): requeued
2020-01-01T01:17:31 | INFO | test_user | getting user object succeeded for /u/requeued
requeued is friend? True
testing account (shadowbanned account, in friends): ELINT_podagric
2020-01-01T01:17:31 | INFO | test_user | getting user object succeeded for /u/ELINT_podagric
2020-01-01T01:17:32 | ERROR | is_friend | exception checking is_friend for /u/ELINT_podagric: received 404 HTTP response
ELINT_podagric is friend? True
testing account (shadowbanned account, not in friends): cassieborowski
2020-01-01T01:17:32 | INFO | test_user | getting user object succeeded for /u/cassieborowski
2020-01-01T01:17:33 | ERROR | is_friend | exception checking is_friend for /u/cassieborowski: received 404 HTTP response
2020-01-01T01:17:33 | ERROR | is_friend | exception checking friends via API for /u/cassieborowski: received 400 HTTP response
cassieborowski is friend? False
testing account (suspended account, in friends): efdi
2020-01-01T01:17:36 | INFO | test_user | getting user object succeeded for /u/efdi
2020-01-01T01:17:36 | ERROR | is_friend | exception checking is_friend for /u/efdi: 'Redditor' object has no attribute 'is_friend'
efdi is friend? True
testing account (suspended account, not in friends): GeneralReposti_Bot
2020-01-01T01:17:37 | INFO | test_user | getting user object succeeded for /u/GeneralReposti_Bot
2020-01-01T01:17:37 | ERROR | is_friend | exception checking is_friend for /u/GeneralReposti_Bot: 'Redditor' object has no attribute 'is_friend'
2020-01-01T01:17:37 | ERROR | is_friend | exception checking friends via API for /u/GeneralReposti_Bot: received 400 HTTP response
#!/usr/bin/python
import praw
import requests
import time
from datetime import datetime
import logging
# setup
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)s | %(funcName)s | %(message)s',
datefmt='%Y-%m-%dT%H:%M:%S',
)
praw_config = {"user_agent": "linux:SOMETHING:v0.1 (by /u/SOMETHING)"}
r = praw.Reddit("SOMETHING", **praw_config)
def is_friend(user):
try:
if type(user) == str:
return r.redditor(user).is_friend
else:
return user.is_friend
except Exception as e:
logging.error("exception checking is_friend for /u/{}: {}".format(user, e))
try:
return r.get("/api/v1/me/friends/" + str(user)) == str(user)
except Exception as e:
logging.error("exception checking friends via API for /u/{}: {}".format(user, e))
# I don't think the next test ever returns True when the previous test could not return
# True, but it seems cleaner to return False this way rather than based on an error.
try:
return user in r.user.friends()
except Exception as e:
logging.error("failed searching entire friends list for /u/{}: {}".format(user, e))
return None
def test_user(info, name):
print("testing account ({}): {}".format(info, name))
try:
user = r.redditor(name)
logging.info("getting user object succeeded for /u/{}".format(user))
except:
logging.error("getting user object failed for /u/{}: {}".format(user, e))
user = name
is_friended = is_friend(user)
print("{} is friend? {}".format(user, is_friended))
print
if __name__ == "__main__":
test_user("normal account, not in friends", "dequeued")
test_user("normal account, in friends", "requeued")
test_user("shadowbanned account, in friends", "ELINT_podagric")
test_user("shadowbanned account, not in friends", "cassieborowski")
test_user("suspended account, in friends", "efdi")
test_user("suspended account, not in friends", "GeneralReposti_Bot")
@dequeued0 what kind of exception is thrown?
@PythonCoderAS The exceptions are shown in the test case output, the first file.
I see. Can you also dump the vars of each Redditor instance, throughvars(<variable holding a Redditor>)
?
Reddit returns 404s for shadowbanned users. this is pretty much expected and correct behavior. otherwise it wouldn't be a shadowban.
permanently suspended (whether by password reset requirement (sometimes) or otherwise) users only return the name
and is_suspended
attribute.
Reddit also returns HTTP 400 always for the other endpoint if you're not friends with a certain user, regardless of their shadowban or suspension status. this is also correct behavior.
a note on deleted accounts: they will show [deleted]
for the username when checking a post or comment (as I believe the use case for this is), so it doesn't really matter anyway.
after 30 days they're removed from your friends list entirely and a note is placed on their account noting this, even though it is inaccessible for the first 30 days or so. Reddit will return 400 in this case for /api/v1/me/friends
but with a different error message.
I think the best way to resolve this issue is to add a note in documentation for suspended or shadowbanned accounts.
This is already documented, no?
This table describes attributes that typically belong to objects of this class. Since attributes are dynamically provided (see Determine Available Attributes of an Object), there is not a guarantee that these attributes will always be present, nor is this list comprehensive in any way.
A user that doesn't exist (as is the case with a shadowbanned user) is obvious to fail. It's easy to verify that it'd fail even on the website
I was thinking about putting a note for suspended accounts, which is not documented. It also doesn't hurt to put a notice about shadowbanned, although suspended should definitely be mentioned.
Furthermore, the calls for getting user object data always succeed because of lazy-loading. Shadowbanned accounts are the same as an incorrect username.
Closing as this is a bug on Reddit's side, not PRAW's side. There is a new method to check for existing friendships, please use that.
this isn't a bug, it's intended behavior on reddit's side though...
Well therefore it's closed as normal behavior.
Issue Description
Checking
.is_friend
doesn't work for suspended and banned (i.e., shadowbanned by Reddit) redditors. Requesting directly via/api/v1/me/friends
does work although an exception is generated if the account is suspended/banned and not in friends.Checking the entire friends list also works, but is much slower for a large friends list, so I am only calling this way in my workaround code if the previous two methods generate exceptions.
I'm attaching a test script to demonstrate the error. I'm using a similar is_friends() function in my production code. Note that it requires you to add some of the accounts to friends to run the test. I'll also include the output.
I'm not sure about the behavior for deleted redditors that are in friends because I cannot add these accounts to friends and I don't happen to have one present in friends. The behavior seems to be the same as shadowbanned acccounts when the deleted account isn't present in friends.
Finally, note that the errors do differ somewhat depending on whether the account is suspended/deleted vs. banned.
System Information
is_friend_testcase.txt
is_friend_testcase.py.txt