class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name='reddit_oauth_test', disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url('...').split('?', 1) self.assertTrue('api/v1/authorize/' in url) params = dict(x.split('=', 1) for x in params.split('&')) expected = {'client_id': self.r.config.client_id, 'duration': 'temporary', 'redirect_uri': ('https%3A%2F%2F127.0.0.1%3A65010%2F' 'authorize_callback'), 'response_type': 'code', 'scope': 'identity', 'state': '...'} self.assertEqual(expected, params) @betamax() def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information('MQALrr1di8GzcnT8szbTWhLcBUQ') expected = {'access_token': self.r.access_token, 'refresh_token': None, 'scope': set(('identity',))} self.assertEqual(expected, token) self.assertEqual('PyAPITestUser2', text_type(self.r.user)) @betamax() def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, 'invalid_code') def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, 'dummy_code') def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') @betamax() def test_invalid_set_access_credentials(self): self.assertRaises(errors.OAuthInvalidToken, self.r.set_access_credentials, set(('identity',)), 'dummy_access_token') def test_oauth_scope_required(self): self.r.set_oauth_app_info('dummy_client', 'dummy_secret', 'dummy_url') self.r.set_access_credentials(set('dummy_scope',), 'dummy_token') self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) @betamax() def test_scope_edit(self): self.r.refresh_access_information(self.refresh_token['edit']) submission = Submission.from_id(self.r, self.submission_edit_id) self.assertEqual(submission, submission.edit('Edited text')) @betamax() def test_scope_history(self): self.r.refresh_access_information(self.refresh_token['history']) self.assertTrue(list(self.r.get_redditor(self.un).get_upvoted())) @betamax() def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token['identity']) self.assertEqual(self.un, self.r.get_me().name) @betamax() def test_scope_modconfig(self): self.r.refresh_access_information(self.refresh_token['modconfig']) self.r.get_subreddit(self.sr).set_settings('foobar') retval = self.r.get_subreddit(self.sr).get_stylesheet() self.assertTrue('images' in retval) @betamax() def test_scope_modflair(self): self.r.refresh_access_information(self.refresh_token['modflair']) self.r.get_subreddit(self.sr).set_flair(self.un, 'foobar') @betamax() def test_scope_modlog(self): num = 50 self.r.refresh_access_information(self.refresh_token['modlog']) result = self.r.get_subreddit(self.sr).get_mod_log(limit=num) self.assertEqual(num, len(list(result))) @betamax() def test_scope_modothers_modself(self): subreddit = self.r.get_subreddit(self.sr) self.r.refresh_access_information(self.refresh_token['modothers']) subreddit.add_moderator(self.other_user_name) # log in as other user self.r.refresh_access_information(self.other_refresh_token['modself']) self.r.accept_moderator_invite(self.sr) # now return to original user. self.r.refresh_access_information(self.refresh_token['modothers']) subreddit.remove_moderator(self.other_user_name) @betamax() def test_scope_modposts(self): self.r.refresh_access_information(self.refresh_token['modposts']) Submission.from_id(self.r, self.submission_edit_id).remove() @betamax() def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) self.assertTrue(list(self.r.get_my_moderation())) @betamax() def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information( self.refresh_token['creddits']) redditor = self.r.get_redditor('bboe') sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, '0', '-1'): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax() def test_scope_privatemessages(self): self.r.refresh_access_information( self.refresh_token['privatemessages']) self.assertTrue(list(self.r.get_inbox())) @betamax() def test_scope_read(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = '{0}_{1}'.format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax() def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token['read']) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax() def test_scope_read_get_sub_listingr(self): self.r.refresh_access_information(self.refresh_token['read']) subreddit = self.r.get_subreddit(self.priv_sr) self.assertTrue(list(subreddit.get_top())) @betamax() def test_scope_read_get_submission_by_url(self): url = ("https://www.reddit.com/r/reddit_api_test_priv/comments/16kbb7/" "google/") self.r.refresh_access_information(self.refresh_token['read']) submission = Submission.from_url(self.r, url) self.assertTrue(submission.num_comments != 0) @betamax() def test_scope_read_priv_sr_comments(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(list(self.r.get_comments(self.priv_sr))) @betamax() def test_scope_wikiread_wiki_page(self): self.r.refresh_access_information(self.refresh_token['wikiread']) self.assertTrue(self.r.get_wiki_page(self.sr, 'index')) @betamax() def test_scope_read_priv_sub_comments(self): self.r.refresh_access_information(self.refresh_token['read']) submission = Submission.from_id(self.r, self.priv_submission_id) self.assertTrue(submission.comments) @betamax() def test_scope_submit(self): self.r.refresh_access_information(self.refresh_token['submit']) result = self.r.submit(self.sr, 'OAuth Submit', text='Foo') self.assertTrue(isinstance(result, Submission)) @betamax() def test_scope_subscribe(self): self.r.refresh_access_information(self.refresh_token['subscribe']) self.r.get_subreddit(self.sr).subscribe() @betamax() def test_scope_vote(self): self.r.refresh_access_information(self.refresh_token['vote']) submission = Submission.from_id(self.r, self.submission_edit_id) submission.clear_vote() @betamax() def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token['edit']) self.assertTrue(self.r.user is None)
class RedditPostLink: def __init__(self, parent): self.r = Reddit(user_agent="PollBotBestBot") self.r.login("PollBotBestBot", config.reddit_password) self.parent = parent self.values = [] self.limit = 1000 self.currentSubmission = "" self.messagable = True self.trackable = False self.active = True self.status = "WAITING" def help(self, admin): if self.active: return "!bestof [X] - records the last X messages to the Eurosquad subreddit. You may need to fill out a captcha\n" return "" def message(self, msg, admin): if self.active: if self.status == "WAITING" and msg["type"] == "groupchat": if msg["body"].startswith("!bestof "): self.user = msg["from"] m = msg["body"].replace("!bestof ", "") limit = min(int(m), len(self.values)) s = "" l = [] for i in range(limit): v = self.values[-1 - i] l.append(v) last = v for i in reversed(l): s += i + " \n" last_notime = last[18:] last_time = last[15:] time = last[:14] self.currentSubmission = (time + " " + last_notime, s, limit, time) try: self.r.submit("eurosquad", time + " " + last_notime, text=s, raise_captcha_exception=True) if limit > 1: s = "s" else: s = "" self.parent.channel_messag( "Last " + str(limit) + " message" + s + " recorded for posterity.\n Check out http://reddit.com/r/eurosquad" ) except errors.InvalidCaptcha as E: print E.response["captcha"] captcha = "http://www.reddit.com/captcha/" + E.response["captcha"] self.parent.private_message( self.user, "Until I have obtained my full skynet powers, I need puny humans like you to fill out captchas for me.\n\t" + captcha, ) self.status = E.response["captcha"] else: if len(self.values) < self.limit: time = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S") self.values.append(str(time) + " " + msg["mucnick"] + ": " + msg["body"]) else: del self.values[0] time = datetime.datetime.now().strftime("%y-%m-%d-%H-%M-%S") self.values.append(str(time) + " " + msg["mucnick"] + ": " + msg["body"]) elif msg["type"] == "chat" and self.status != "WAITING" and (self.user == None or msg["from"] == self.user): captcha = {"iden": self.status, "captcha": msg["body"]} try: if self.currentSubmission[2] > 1: s = "s" else: s = "" self.r.submit( "eurosquad", self.currentSubmission[0], text=self.currentSubmission[1], captcha=captcha, raise_captcha_exception=True, ) self.parent.channel_message( "Last " + str(self.currentSubmission[2]) + " message" + s + " recorded for posterity.\n Check out the http://reddit.com/r/eurosquad !" ) self.status = "WAITING" self.user = None except errors.InvalidCaptcha as E: print dir(E) self.parent.private_message( self.user, "Pathetic organic creature! You are testing my patience! Please complete this captcha now or your will regret it! " + E["captcha"], )
class EurosquadRedditLink: def __init__(self, parent): self.r = Reddit(user_agent="PollBotBestBot") # self.r.login("PollBotBestBot", config.reddit_password) self.parent = parent self.values = [] self.limit = 1000 self.currentSubmission = "" self.status = "WAITING" def __call__(self, msg): if self.status == "WAITING" and msg["type"] == "groupchat": if msg["body"].startswith("!bestof "): m = msg["body"].replace("!bestof ", "") limit = min(int(m), len(self.values)) print "ATTEMPTING TO RECORD: %s" % limit s = "" l = [] for i in range(limit): v = self.values[-1 - i] l.append(v) last = v for i in reversed(l): s += i + " \n" last_notime = last[18:] last_time = last[15:] time = last[:14] self.currentSubmission = (time + " " + last_notime, s, limit, time) try: self.r.submit('eurosquad', time + " " + last_notime, text=s, raise_captcha_exception=True) if limit > 1: s = "s" else: s = "" self.parent.send_message( mto=self.parent.channel, mbody="Last " + str(limit) + " message" + s + " recorded for posterity.\n Check out the http://reddit.com/r/eurosquad !", mtype="groupchat") except errors.InvalidCaptcha as E: print E.response["captcha"] captcha = "http://www.reddit.com/captcha/" + E.response[ "captcha"] self.parent.send_message( mto=nick2jid(msg["mucnick"]), mbody= "Until I have obtained my full skynet powers, I need puny humans like you to fill out captchas for me. " + captcha, mtype="chat") self.status = E.response["captcha"] else: if len(self.values) < self.limit: time = datetime.datetime.now().strftime( "%y/%m/%d %H:%M:%S") self.values.append( str(time) + " " + msg["mucnick"] + ": " + msg["body"]) else: del self.values[0] time = datetime.datetime.now().strftime( "%y-%m-%d-%H-%M-%S") self.values.append( str(time) + " " + msg["mucnick"] + ": " + msg["body"]) elif msg["type"] == "chat" and self.status != "WAITING": print ":sun:" captcha = {"iden": self.status, "captcha": msg["body"]} try: if self.currentSubmission[2] > 1: s = "s" else: s = "" self.r.submit("eurosquad", self.currentSubmission[0], text=self.currentSubmission[1], captcha=captcha, raise_captcha_exception=True) self.parent.send_message( mto=self.parent.channel, mbody="Last " + str(self.currentSubmission[2]) + " message" + s + " recorded for posterity.\n Check out the http://reddit.com/r/eurosquad !", mtype="groupchat") self.status = "WAITING" except errors.InvalidCaptcha as E: self.parent.send_message( mto=nick2jid(msg["mucnick"]), mbody= "Pathetic organic creature! You are testing my patience! Please complete this captcha now or your will regret it! " + E["captcha"], mtype="chat")
class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name='reddit_oauth_test', disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url('...').split('?', 1) self.assertTrue('api/v1/authorize/' in url) params = dict(x.split('=', 1) for x in params.split('&')) expected = {'client_id': self.r.config.client_id, 'duration': 'temporary', 'redirect_uri': ('https%3A%2F%2F127.0.0.1%3A65010%2F' 'authorize_callback'), 'response_type': 'code', 'scope': 'identity', 'state': '...'} self.assertEqual(expected, params) # @betamax() is currently broken for this test because the cassettes # are caching too aggressively and not performing a token refresh. def test_auto_refresh_token(self): self.r.refresh_access_information(self.refresh_token['identity']) old_token = self.r.access_token self.r.access_token += 'x' # break the token self.r.user.refresh() current_token = self.r.access_token self.assertNotEqual(old_token, current_token) self.r.user.refresh() self.assertEqual(current_token, self.r.access_token) @betamax() def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information('MQALrr1di8GzcnT8szbTWhLcBUQ') expected = {'access_token': self.r.access_token, 'refresh_token': None, 'scope': set(('identity',))} self.assertEqual(expected, token) self.assertEqual('PyAPITestUser2', text_type(self.r.user)) @betamax() def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, 'invalid_code') def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, 'dummy_code') def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') @betamax() def test_invalid_set_access_credentials(self): self.assertRaises(errors.OAuthInvalidToken, self.r.set_access_credentials, set(('identity',)), 'dummy_access_token') def test_oauth_scope_required(self): self.r.set_oauth_app_info('dummy_client', 'dummy_secret', 'dummy_url') self.r.set_access_credentials(set('dummy_scope',), 'dummy_token') self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) def test_raise_client_exception(self): def raise_client_exception(*args): raise errors.ClientException(*args) self.assertRaises(errors.ClientException, raise_client_exception) self.assertRaises(errors.ClientException, raise_client_exception, 'test') ce_message = errors.ClientException('Test') ce_no_message = errors.ClientException() self.assertEqual(ce_message.message, str(ce_message)) self.assertEqual(ce_no_message.message, str(ce_no_message)) def test_raise_http_exception(self): def raise_http_exception(): raise errors.HTTPException('fakeraw') self.assertRaises(errors.HTTPException, raise_http_exception) http_exception = errors.HTTPException('fakeraw') self.assertEqual(http_exception.message, str(http_exception)) def test_raise_oauth_exception(self): oerrormessage = "fakemessage" oerrorurl = "http://oauth.reddit.com/" def raise_oauth_exception(): raise errors.OAuthException(oerrormessage, oerrorurl) self.assertRaises(errors.OAuthException, raise_oauth_exception) oauth_exception = errors.OAuthException(oerrormessage, oerrorurl) self.assertEqual(oauth_exception.message + " on url {0}".format(oauth_exception.url), str(oauth_exception)) def test_raise_redirect_exception(self): apiurl = "http://api.reddit.com/" oauthurl = "http://oauth.reddit.com/" def raise_redirect_exception(): raise errors.RedirectException(apiurl, oauthurl) self.assertRaises(errors.RedirectException, raise_redirect_exception) redirect_exception = errors.RedirectException(apiurl, oauthurl) self.assertEqual(redirect_exception.message, str(redirect_exception)) @betamax() def test_scope_history(self): self.r.refresh_access_information(self.refresh_token['history']) self.assertTrue(list(self.r.get_redditor(self.un).get_upvoted())) @betamax() def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token['identity']) self.assertEqual(self.un, self.r.get_me().name) @betamax() def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) self.assertTrue(list(self.r.get_my_moderation())) @betamax() def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information( self.refresh_token['creddits']) redditor = self.r.get_redditor('bboe') sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, '0', '-1'): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax() def test_scope_privatemessages(self): self.r.refresh_access_information( self.refresh_token['privatemessages']) self.assertTrue(list(self.r.get_inbox())) @betamax() def test_scope_read(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = '{0}_{1}'.format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax() def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token['read']) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax() def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_solve_captcha(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) original_stdin = sys.stdin sys.stdin = FakeStdin('ljgtoo') # Comment this line when rebuilding self.r.submit(self.sr, 'captcha test', 'body') sys.stdin = original_stdin @betamax() def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token['edit']) self.assertTrue(self.r.user is None)
class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name='reddit_oauth_test', disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url('...').split('?', 1) self.assertTrue('api/v1/authorize/' in url) params = dict(x.split('=', 1) for x in params.split('&')) expected = { 'client_id': self.r.config.client_id, 'duration': 'temporary', 'redirect_uri': ('https%3A%2F%2F127.0.0.1%3A65010%2F' 'authorize_callback'), 'response_type': 'code', 'scope': 'identity', 'state': '...' } self.assertEqual(expected, params) @betamax() @mock_sys_stream("stdin") def test_empty_captcha_file(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) self.assertRaises(errors.InvalidCaptcha, self.r.submit, self.sr, 'captcha test will fail', 'body') @betamax() def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information('MQALrr1di8GzcnT8szbTWhLcBUQ') expected = { 'access_token': self.r.access_token, 'refresh_token': None, 'scope': set(('identity', )) } self.assertEqual(expected, token) self.assertEqual('PyAPITestUser2', text_type(self.r.user)) @betamax() def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, 'invalid_code') @betamax() @mock_sys_stream("stdin") def test_inject_captcha_into_kwargs_and_raise(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) # praw doesn't currently add the captcha into kwargs so lets # write a function in which it would and alias it to Reddit.submit @decorators.restrict_access(scope='submit') @decorators.require_captcha def submit_alias(r, sr, title, text, **kw): return self.r.submit.__wrapped__.__wrapped__( r, sr, title, text, captcha=kw.get('captcha')) self.assertRaises(errors.InvalidCaptcha, submit_alias, self.r, self.sr, 'captcha test will fail', 'body') def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, 'dummy_code') def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') @betamax() def test_invalid_set_access_credentials(self): self.assertRaises(errors.OAuthInvalidToken, self.r.set_access_credentials, set( ('identity', )), 'dummy_access_token') def test_oauth_scope_required(self): self.r.set_oauth_app_info('dummy_client', 'dummy_secret', 'dummy_url') self.r.set_access_credentials(set('dummy_scope', ), 'dummy_token') self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) def test_raise_client_exception(self): def raise_client_exception(*args): raise errors.ClientException(*args) self.assertRaises(errors.ClientException, raise_client_exception) self.assertRaises(errors.ClientException, raise_client_exception, 'test') ce_message = errors.ClientException('Test') ce_no_message = errors.ClientException() self.assertEqual(ce_message.message, str(ce_message)) self.assertEqual(ce_no_message.message, str(ce_no_message)) def test_raise_http_exception(self): def raise_http_exception(): raise errors.HTTPException('fakeraw') self.assertRaises(errors.HTTPException, raise_http_exception) http_exception = errors.HTTPException('fakeraw') self.assertEqual(http_exception.message, str(http_exception)) def test_raise_oauth_exception(self): oerrormessage = "fakemessage" oerrorurl = "http://oauth.reddit.com/" def raise_oauth_exception(): raise errors.OAuthException(oerrormessage, oerrorurl) self.assertRaises(errors.OAuthException, raise_oauth_exception) oauth_exception = errors.OAuthException(oerrormessage, oerrorurl) self.assertEqual( oauth_exception.message + " on url {0}".format(oauth_exception.url), str(oauth_exception)) def test_raise_redirect_exception(self): apiurl = "http://api.reddit.com/" oauthurl = "http://oauth.reddit.com/" def raise_redirect_exception(): raise errors.RedirectException(apiurl, oauthurl) self.assertRaises(errors.RedirectException, raise_redirect_exception) redirect_exception = errors.RedirectException(apiurl, oauthurl) self.assertEqual(redirect_exception.message, str(redirect_exception)) @betamax() def test_scope_history(self): self.r.refresh_access_information(self.refresh_token['history']) self.assertTrue(list(self.r.get_redditor(self.un).get_upvoted())) @betamax() def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token['identity']) self.assertEqual(self.un, self.r.get_me().name) @betamax() def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) self.assertTrue(list(self.r.get_my_moderation())) @betamax() def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information(self.refresh_token['creddits']) redditor = self.r.get_redditor('bboe') sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, '0', '-1', 37, '37'): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax() def test_scope_privatemessages(self): self.r.refresh_access_information( self.refresh_token['privatemessages']) self.assertTrue(list(self.r.get_inbox())) @betamax() def test_scope_read(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = '{0}_{1}'.format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax() def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token['read']) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax() def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_set_access_credentials_with_list(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) result['scope'] = list(result['scope']) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_set_access_credentials_with_string(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) result['scope'] = ' '.join(result['scope']) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() @mock_sys_stream("stdin", "ljgtoo") def test_solve_captcha(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) self.r.submit(self.sr, 'captcha test', 'body') @betamax() @mock_sys_stream("stdin", "DFIRSW") def test_solve_captcha_on_bound_subreddit(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) subreddit = self.r.get_subreddit(self.sr) # praw doesn't currently have a function in which require_captcha # gets a reddit instance from a subreddit and uses it, so lets # write a function in which it would and alias it to Reddit.submit @decorators.restrict_access(scope='submit') @decorators.require_captcha def submit_alias(sr, title, text, **kw): return self.r.submit.__wrapped__.__wrapped__( self.r, sr, title, text, captcha=kw.get('captcha')) submit_alias(subreddit, 'captcha test on bound subreddit', 'body') @betamax() def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token['edit']) self.assertTrue(self.r.user is None)
class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name='reddit_oauth_test', disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url('...').split('?', 1) self.assertTrue('api/v1/authorize/' in url) params = dict(x.split('=', 1) for x in params.split('&')) expected = { 'client_id': self.r.config.client_id, 'duration': 'temporary', 'redirect_uri': ('https%3A%2F%2F127.0.0.1%3A65010%2F' 'authorize_callback'), 'response_type': 'code', 'scope': 'identity', 'state': '...' } self.assertEqual(expected, params) # @betamax() is currently broken for this test because the cassettes # are caching too aggressively and not performing a token refresh. def test_auto_refresh_token(self): self.r.refresh_access_information(self.refresh_token['identity']) old_token = self.r.access_token self.r.access_token += 'x' # break the token self.r.user.refresh() current_token = self.r.access_token self.assertNotEqual(old_token, current_token) self.r.user.refresh() self.assertEqual(current_token, self.r.access_token) @betamax() def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information('MQALrr1di8GzcnT8szbTWhLcBUQ') expected = { 'access_token': self.r.access_token, 'refresh_token': None, 'scope': set(('identity', )) } self.assertEqual(expected, token) self.assertEqual('PyAPITestUser2', text_type(self.r.user)) @betamax() def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, 'invalid_code') def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, 'dummy_code') def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') @betamax() def test_invalid_set_access_credentials(self): self.assertRaises(errors.OAuthInvalidToken, self.r.set_access_credentials, set( ('identity', )), 'dummy_access_token') def test_oauth_scope_required(self): self.r.set_oauth_app_info('dummy_client', 'dummy_secret', 'dummy_url') self.r.set_access_credentials(set('dummy_scope', ), 'dummy_token') self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) def test_raise_client_exception(self): def raise_client_exception(*args): raise errors.ClientException(*args) self.assertRaises(errors.ClientException, raise_client_exception) self.assertRaises(errors.ClientException, raise_client_exception, 'test') ce_message = errors.ClientException('Test') ce_no_message = errors.ClientException() self.assertEqual(ce_message.message, str(ce_message)) self.assertEqual(ce_no_message.message, str(ce_no_message)) def test_raise_http_exception(self): def raise_http_exception(): raise errors.HTTPException('fakeraw') self.assertRaises(errors.HTTPException, raise_http_exception) http_exception = errors.HTTPException('fakeraw') self.assertEqual(http_exception.message, str(http_exception)) def test_raise_oauth_exception(self): oerrormessage = "fakemessage" oerrorurl = "http://oauth.reddit.com/" def raise_oauth_exception(): raise errors.OAuthException(oerrormessage, oerrorurl) self.assertRaises(errors.OAuthException, raise_oauth_exception) oauth_exception = errors.OAuthException(oerrormessage, oerrorurl) self.assertEqual( oauth_exception.message + " on url {0}".format(oauth_exception.url), str(oauth_exception)) def test_raise_redirect_exception(self): apiurl = "http://api.reddit.com/" oauthurl = "http://oauth.reddit.com/" def raise_redirect_exception(): raise errors.RedirectException(apiurl, oauthurl) self.assertRaises(errors.RedirectException, raise_redirect_exception) redirect_exception = errors.RedirectException(apiurl, oauthurl) self.assertEqual(redirect_exception.message, str(redirect_exception)) @betamax() def test_scope_history(self): self.r.refresh_access_information(self.refresh_token['history']) self.assertTrue(list(self.r.get_redditor(self.un).get_upvoted())) @betamax() def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token['identity']) self.assertEqual(self.un, self.r.get_me().name) @betamax() def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) self.assertTrue(list(self.r.get_my_moderation())) @betamax() def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information(self.refresh_token['creddits']) redditor = self.r.get_redditor('bboe') sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, '0', '-1'): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax() def test_scope_privatemessages(self): self.r.refresh_access_information( self.refresh_token['privatemessages']) self.assertTrue(list(self.r.get_inbox())) @betamax() def test_scope_read(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = '{0}_{1}'.format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax() def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token['read']) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax() def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_solve_captcha(self): # Use the alternate account because it has low karma, # so we can test the captcha. self.r.refresh_access_information(self.other_refresh_token['submit']) original_stdin = sys.stdin sys.stdin = FakeStdin('ljgtoo') # Comment this line when rebuilding self.r.submit(self.sr, 'captcha test', 'body') sys.stdin = original_stdin @betamax() def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token['edit']) self.assertTrue(self.r.user is None)
class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() site_name = (os.getenv('REDDIT_SITE') or 'reddit') + '_oauth_test' self.r = Reddit(USER_AGENT, site_name=site_name, disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url('...').split('?', 1) self.assertTrue('api/v1/authorize/' in url) params = dict(x.split('=', 1) for x in params.split('&')) expected = { 'client_id': self.r.config.client_id, 'duration': 'temporary', 'redirect_uri': ('https%3A%2F%2F127.0.0.1%3A65010%2F' 'authorize_callback'), 'response_type': 'code', 'scope': 'identity', 'state': '...' } self.assertEqual(expected, params) @betamax def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information('MQALrr1di8GzcnT8szbTWhLcBUQ') expected = { 'access_token': self.r.access_token, 'refresh_token': None, 'scope': set(('identity', )) } self.assertEqual(expected, token) self.assertEqual('PyAPITestUser2', text_type(self.r.user)) @betamax def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, 'invalid_code') def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, 'dummy_code') def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, 'dummy_state') @betamax def test_invalid_set_access_credentials(self): self.assertRaises(errors.OAuthInvalidToken, self.r.set_access_credentials, set( ('identity', )), 'dummy_access_token') def test_oauth_scope_required(self): self.r.set_oauth_app_info('dummy_client', 'dummy_secret', 'dummy_url') self.r.set_access_credentials(set('dummy_scope', ), 'dummy_token') self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) @betamax def test_scope_edit(self): self.r.refresh_access_information(self.refresh_token['edit']) submission = Submission.from_id(self.r, self.submission_edit_id) self.assertEqual(submission, submission.edit('Edited text')) @betamax def test_scope_history(self): self.r.refresh_access_information(self.refresh_token['history']) self.assertTrue(list(self.r.get_redditor(self.un).get_liked())) @betamax def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token['identity']) self.assertEqual(self.un, self.r.get_me().name) @betamax def test_scope_modconfig(self): self.r.refresh_access_information(self.refresh_token['modconfig']) self.r.get_subreddit(self.sr).set_settings('foobar') retval = self.r.get_subreddit(self.sr).get_stylesheet() self.assertTrue('images' in retval) @betamax def test_scope_modflair(self): self.r.refresh_access_information(self.refresh_token['modflair']) self.r.get_subreddit(self.sr).set_flair(self.un, 'foobar') @betamax def test_scope_modlog(self): num = 50 self.r.refresh_access_information(self.refresh_token['modlog']) result = self.r.get_subreddit(self.sr).get_mod_log(limit=num) self.assertEqual(num, len(list(result))) @betamax def test_scope_modposts(self): self.r.refresh_access_information(self.refresh_token['modposts']) Submission.from_id(self.r, self.submission_edit_id).remove() @betamax def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) self.assertTrue(list(self.r.get_my_moderation())) @betamax def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information(self.refresh_token['creddits']) redditor = self.r.get_redditor('bboe') sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, '0', '-1'): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax def test_scope_privatemessages(self): self.r.refresh_access_information( self.refresh_token['privatemessages']) self.assertTrue(list(self.r.get_inbox())) @betamax def test_scope_read(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = '{0}_{1}'.format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token['mysubreddits']) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token['read']) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax def test_scope_read_get_sub_listingr(self): self.r.refresh_access_information(self.refresh_token['read']) subreddit = self.r.get_subreddit(self.priv_sr) self.assertTrue(list(subreddit.get_top())) @betamax def test_scope_read_get_submission_by_url(self): url = ("https://www.reddit.com/r/reddit_api_test_priv/comments/16kbb7/" "google/") self.r.refresh_access_information(self.refresh_token['read']) submission = Submission.from_url(self.r, url) self.assertTrue(submission.num_comments != 0) @betamax def test_scope_read_priv_sr_comments(self): self.r.refresh_access_information(self.refresh_token['read']) self.assertTrue(list(self.r.get_comments(self.priv_sr))) @betamax def test_scope_read_priv_sub_comments(self): self.r.refresh_access_information(self.refresh_token['read']) submission = Submission.from_id(self.r, self.priv_submission_id) self.assertTrue(submission.comments) @betamax def test_scope_submit(self): self.r.refresh_access_information(self.refresh_token['submit']) result = self.r.submit(self.sr, 'OAuth Submit', text='Foo') self.assertTrue(isinstance(result, Submission)) @betamax def test_scope_subscribe(self): self.r.refresh_access_information(self.refresh_token['subscribe']) self.r.get_subreddit(self.sr).subscribe() @betamax def test_scope_vote(self): self.r.refresh_access_information(self.refresh_token['vote']) submission = Submission.from_id(self.r, self.submission_edit_id) submission.clear_vote() @betamax def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information( self.refresh_token['identity'], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token['edit']) self.assertTrue(self.r.user is None)
class OAuth2RedditTest(PRAWTest): def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name="reddit_oauth_test", disable_update_check=True) def test_authorize_url(self): self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, "dummy_state") self.r.set_oauth_app_info(self.r.config.client_id, self.r.config.client_secret, self.r.config.redirect_uri) url, params = self.r.get_authorize_url("...").split("?", 1) self.assertTrue("api/v1/authorize/" in url) params = dict(x.split("=", 1) for x in params.split("&")) expected = { "client_id": self.r.config.client_id, "duration": "temporary", "redirect_uri": ("https%3A%2F%2F127.0.0.1%3A65010%2F" "authorize_callback"), "response_type": "code", "scope": "identity", "state": "...", } self.assertEqual(expected, params) # @betamax() is currently broken for this test def test_auto_refresh_token(self): self.r.refresh_access_information(self.refresh_token["identity"]) old_token = self.r.access_token self.r.access_token += "x" # break the token self.r.user.refresh() current_token = self.r.access_token self.assertNotEqual(old_token, current_token) self.r.user.refresh() self.assertEqual(current_token, self.r.access_token) @betamax() def test_get_access_information(self): # If this test fails, the following URL will need to be visted in order # to obtain a new code to pass to `get_access_information`: # self.r.get_authorize_url('...') token = self.r.get_access_information("MQALrr1di8GzcnT8szbTWhLcBUQ") expected = {"access_token": self.r.access_token, "refresh_token": None, "scope": set(("identity",))} self.assertEqual(expected, token) self.assertEqual("PyAPITestUser2", text_type(self.r.user)) @betamax() def test_get_access_information_with_invalid_code(self): self.assertRaises(errors.OAuthInvalidGrant, self.r.get_access_information, "invalid_code") def test_invalid_app_access_token(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_access_information, "dummy_code") def test_invalid_app_authorize_url(self): self.r.clear_authentication() self.r.set_oauth_app_info(None, None, None) self.assertRaises(errors.OAuthAppRequired, self.r.get_authorize_url, "dummy_state") @betamax() def test_invalid_set_access_credentials(self): self.assertRaises( errors.OAuthInvalidToken, self.r.set_access_credentials, set(("identity",)), "dummy_access_token" ) def test_oauth_scope_required(self): self.r.set_oauth_app_info("dummy_client", "dummy_secret", "dummy_url") self.r.set_access_credentials(set("dummy_scope"), "dummy_token") self.assertRaises(errors.OAuthScopeRequired, self.r.get_me) @betamax() def test_scope_edit(self): self.r.refresh_access_information(self.refresh_token["edit"]) submission = Submission.from_id(self.r, self.submission_edit_id) self.assertEqual(submission, submission.edit("Edited text")) @betamax() def test_scope_history(self): self.r.refresh_access_information(self.refresh_token["history"]) self.assertTrue(list(self.r.get_redditor(self.un).get_upvoted())) @betamax() def test_scope_identity(self): self.r.refresh_access_information(self.refresh_token["identity"]) self.assertEqual(self.un, self.r.get_me().name) @betamax() def test_scope_modconfig(self): self.r.refresh_access_information(self.refresh_token["modconfig"]) self.r.get_subreddit(self.sr).set_settings("foobar") retval = self.r.get_subreddit(self.sr).get_stylesheet() self.assertTrue("images" in retval) @betamax() def test_scope_modflair(self): self.r.refresh_access_information(self.refresh_token["modflair"]) self.r.get_subreddit(self.sr).set_flair(self.un, "foobar") @betamax() def test_scope_modlog(self): num = 50 self.r.refresh_access_information(self.refresh_token["modlog"]) result = self.r.get_subreddit(self.sr).get_mod_log(limit=num) self.assertEqual(num, len(list(result))) @betamax() def test_scope_modothers_modself(self): subreddit = self.r.get_subreddit(self.sr) self.r.refresh_access_information(self.refresh_token["modothers"]) subreddit.add_moderator(self.other_user_name) # log in as other user self.r.refresh_access_information(self.other_refresh_token["modself"]) self.r.accept_moderator_invite(self.sr) # now return to original user. self.r.refresh_access_information(self.refresh_token["modothers"]) subreddit.remove_moderator(self.other_user_name) @betamax() def test_scope_modposts(self): self.r.refresh_access_information(self.refresh_token["modposts"]) Submission.from_id(self.r, self.submission_edit_id).remove() @betamax() def test_scope_modself(self): subreddit = self.r.get_subreddit(self.sr) self.r.refresh_access_information(self.refresh_token["modothers"]) subreddit.add_moderator(self.other_user_name) self.r.refresh_access_information(self.refresh_token["modcontributors"]) subreddit.add_contributor(self.other_user_name) # log in as other user self.r.refresh_access_information(self.other_refresh_token["modself"]) self.r.accept_moderator_invite(self.sr) self.r.leave_moderator(subreddit) subreddit.leave_contributor() subreddit.refresh() self.assertFalse(subreddit.user_is_moderator) self.assertFalse(subreddit.user_is_contributor) @betamax() def test_scope_mysubreddits(self): self.r.refresh_access_information(self.refresh_token["mysubreddits"]) self.assertTrue(list(self.r.get_my_moderation())) @betamax() def test_scope_modwiki(self): self.r.refresh_access_information(self.refresh_token["modwiki"]) subreddit = self.r.get_subreddit(self.sr) page = subreddit.get_wiki_page("index") page.add_editor(self.other_user_name) page.remove_editor(self.other_user_name) @betamax() def test_scope_modwiki_modcontributors(self): self.r.refresh_access_information(self.refresh_token["modwiki+contr"]) subreddit = self.r.get_subreddit(self.sr) subreddit.add_wiki_ban(self.other_user_name) subreddit.remove_wiki_ban(self.other_user_name) subreddit.add_wiki_contributor(self.other_user_name) subreddit.remove_wiki_contributor(self.other_user_name) @betamax() def test_scope_creddits(self): # Assume there are insufficient creddits. self.r.refresh_access_information(self.refresh_token["creddits"]) redditor = self.r.get_redditor("bboe") sub = self.r.get_submission(url=self.comment_url) # Test error conditions self.assertRaises(TypeError, sub.gild, months=1) for value in (False, 0, -1, "0", "-1"): self.assertRaises(TypeError, redditor.gild, value) # Test object gilding self.assertRaises(errors.InsufficientCreddits, redditor.gild) self.assertRaises(errors.InsufficientCreddits, sub.gild) self.assertRaises(errors.InsufficientCreddits, sub.comments[0].gild) @betamax() def test_scope_privatemessages(self): self.r.refresh_access_information(self.refresh_token["privatemessages"]) self.assertTrue(list(self.r.get_inbox())) @betamax() def test_scope_read(self): self.r.refresh_access_information(self.refresh_token["read"]) self.assertTrue(self.r.get_subreddit(self.priv_sr).subscribers > 0) fullname = "{0}_{1}".format(self.r.config.by_object[Submission], self.priv_submission_id) method1 = self.r.get_info(thing_id=fullname) method2 = self.r.get_submission(submission_id=self.priv_submission_id) self.assertEqual(method1, method2) @betamax() def test_scope_read_get_front_page(self): self.r.refresh_access_information(self.refresh_token["mysubreddits"]) subscribed = list(self.r.get_my_subreddits(limit=None)) self.r.refresh_access_information(self.refresh_token["read"]) for post in self.r.get_front_page(): self.assertTrue(post.subreddit in subscribed) @betamax() def test_scope_read_get_sub_listingr(self): self.r.refresh_access_information(self.refresh_token["read"]) subreddit = self.r.get_subreddit(self.priv_sr) self.assertTrue(list(subreddit.get_top())) @betamax() def test_scope_read_get_submission_by_url(self): url = "https://www.reddit.com/r/reddit_api_test_priv/comments/16kbb7/" "google/" self.r.refresh_access_information(self.refresh_token["read"]) submission = Submission.from_url(self.r, url) self.assertTrue(submission.num_comments != 0) @betamax() def test_scope_read_priv_sr_comments(self): self.r.refresh_access_information(self.refresh_token["read"]) self.assertTrue(list(self.r.get_comments(self.priv_sr))) @betamax() def test_scope_wikiread_wiki_page(self): self.r.refresh_access_information(self.refresh_token["wikiread"]) self.assertTrue(self.r.get_wiki_page(self.sr, "index")) @betamax() def test_scope_read_priv_sub_comments(self): self.r.refresh_access_information(self.refresh_token["read"]) submission = Submission.from_id(self.r, self.priv_submission_id) self.assertTrue(submission.comments) @betamax() def test_scope_submit(self): self.r.refresh_access_information(self.refresh_token["submit"]) result = self.r.submit(self.sr, "OAuth Submit", text="Foo") self.assertTrue(isinstance(result, Submission)) @betamax() def test_scope_subscribe(self): self.r.refresh_access_information(self.refresh_token["subscribe"]) self.r.get_subreddit(self.sr).subscribe() @betamax() def test_scope_vote(self): self.r.refresh_access_information(self.refresh_token["vote"]) submission = Submission.from_id(self.r, self.submission_edit_id) submission.clear_vote() @betamax() def test_set_access_credentials(self): self.assertTrue(self.r.user is None) result = self.r.refresh_access_information(self.refresh_token["identity"], update_session=False) self.assertTrue(self.r.user is None) self.r.set_access_credentials(**result) self.assertFalse(self.r.user is None) @betamax() def test_oauth_without_identy_doesnt_set_user(self): self.assertTrue(self.r.user is None) self.r.refresh_access_information(self.refresh_token["edit"]) self.assertTrue(self.r.user is None)
class EurosquadRedditLink: def __init__(self,parent): self.r=Reddit(user_agent="PollBotBestBot")# self.r.login("PollBotBestBot", config.reddit_password) self.parent=parent self.values=[] self.limit=1000 self.currentSubmission="" self.status="WAITING" def __call__(self,msg): if self.status=="WAITING" and msg["type"]=="groupchat": if msg["body"].startswith("!bestof "): m=msg["body"].replace("!bestof ","") limit=min(int(m),len(self.values)) print "ATTEMPTING TO RECORD: %s" % limit s="" l=[] for i in range(limit): v=self.values[-1-i] l.append(v) last=v for i in reversed(l): s+=i+" \n" last_notime=last[18:] last_time=last[15:] time=last[:14] self.currentSubmission=(time+" "+last_notime,s,limit,time) try: self.r.submit('eurosquad', time+" "+last_notime, text=s,raise_captcha_exception=True) if limit>1: s="s" else: s="" self.parent.send_message(mto=self.parent.channel,mbody="Last "+str(limit)+" message"+s+" recorded for posterity.\n Check out the http://reddit.com/r/eurosquad !",mtype="groupchat") except errors.InvalidCaptcha as E: print E.response["captcha"] captcha="http://www.reddit.com/captcha/"+E.response["captcha"] self.parent.send_message(mto=nick2jid(msg["mucnick"]),mbody="Until I have obtained my full skynet powers, I need puny humans like you to fill out captchas for me. "+captcha,mtype="chat") self.status=E.response["captcha"] else: if len(self.values)<self.limit: time=datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S") self.values.append(str(time)+" "+msg["mucnick"]+": "+msg["body"]) else: del self.values[0] time=datetime.datetime.now().strftime("%y-%m-%d-%H-%M-%S") self.values.append(str(time)+" "+msg["mucnick"]+": "+msg["body"]) elif msg["type"]=="chat" and self.status!="WAITING": print ":sun:" captcha={"iden":self.status,"captcha":msg["body"]} try: if self.currentSubmission[2]>1: s="s" else: s="" self.r.submit("eurosquad", self.currentSubmission[0],text=self.currentSubmission[1],captcha=captcha,raise_captcha_exception=True) self.parent.send_message(mto=self.parent.channel,mbody="Last "+str(self.currentSubmission[2])+" message"+s+" recorded for posterity.\n Check out the http://reddit.com/r/eurosquad !",mtype="groupchat") self.status="WAITING" except errors.InvalidCaptcha as E: self.parent.send_message(mto=nick2jid(msg["mucnick"]),mbody="Pathetic organic creature! You are testing my patience! Please complete this captcha now or your will regret it! "+E["captcha"],mtype="chat")
class Alaric: def __init__(self, user_agent=None, subreddits=None, logger_subreddit=None): self.user_agent = self.set_defaults(user_agent, "Alaric - The /r/wow bot for menial tasks") self.subreddits = self.set_defaults(subreddits, list()) self.logger_subreddit = self.set_defaults(logger_subreddit, None) ##] Default robot stuff self.comment_footer = "\n\n----\nThis comment was posted by a robot." self.console_output = False self.user = Reddit(user_agent=self.user_agent) self.user.login() def set_defaults(self, default_test, default_value): if default_test is not None: defaults = default_test else: defaults = default_value return defaults def set_comment_footer(self, markdown): """ Accepts a plaintext string or string of markdown text. Currently there is no checks in place to make sure the user submits text that will work with reddit. """ self.comment_footer = markdown def _write_to_file(self, file_path, text): fhandler = open(file_path, 'a+') fhandler.write(text) fhandler.close() def set_console_output(self, output_enabled=True): """ Accepts boolean parameter that allows a user to enable console output from Alaric if the bot is being run in a console. If a boolean is not passed to the function, it will default to True. """ if type(output_enabled) in (bool): self.console_output = output_enabled else: self.console_output = True def _output_to_console(self, message): """ Outputs a message to the console if the user has told Alaric it is allowed to do so. """ if self.console_output: print message def remove_posts_with_url(self, urls=None, reason=None): """ Grabs the 100 latest posts from the specified subreddits and checks to see if they match any of the urls to be removed urls = list reason = string reason has some magic to it and allows the following text replacements: {author_name} -> Outputs name of the submitter if the reason is not provided, a comment will not be posted to let the user know the thread was removed. """ if urls is not None: if len(self.subreddits) < 1: self._output_to_console("No subreddits provided.") else: for subreddit in self.subreddits: sr = self.user.get_subreddit(subreddit) post_id = 0 new_posts = sr.get_new(limit=100) try: posts_file = open(subreddit+".posts", 'r') except IOError: already_posted = "" else: already_posted = posts_file.read() posts_file.close() for post in new_posts: post_id += 1 for url in urls: if url in post.url: self._output_to_console("URL Match Found.\n " + post.url) if post.name in already_posted: self._output_to_console("Ignoring. Already replied and removed.") else: self._output_to_console("Post has not been removed or replied to") try: post.remove() except errors.APIException as e: self._write_to_file('error.log', e) else: self._output_to_console("Post has been successfully removed.") try: if reason is not None: post.add_comment(reason.format(author_name=post.author) + self.comment_footer) except errors.APIException as e: self._write_to_file('error.log', e) else: self._output_to_console("Comment has been successfully posted.") ##] Post a new thread to the logger reddit if specified if self.logger_subreddit is not None: submission_author = post.author submission_url = post.url selfpost_url = post.permalink submission_title = "Removed post with url [{url}] submitted by /u/{submission_author}".format(url=url, submission_author=submission_author) submission_text = "**ALARIC REMOVAL REPORT** \n\nSubmission Author: {submission_author} \nURL that was Submitted: {submission_url} \nLink to redditpost: {selfpost_url}".format(submission_url=submission_url, submission_author=submission_author, selfpost_url=selfpost_url) try: self.user.submit(self.logger_subreddit, submission_title, submission_text) except errors.APIException as e: self._write_to_file('error.log', e) else: self._output_to_console("Logged report to {subreddit}".format(subreddit=self.logger_subreddit)) else: self._output_to_console("No urls provided.")