def test_delete(self, _): self.reddit.read_only = False with self.recorder.use_cassette('TestComment.test_delete'): comment = Comment(self.reddit, 'd1616q2') comment.delete() assert comment.author is None assert comment.body == '[deleted]'
def test_edit(self, _): self.reddit.read_only = False with self.recorder.use_cassette( 'TestComment.test_edit'): comment = Comment(self.reddit, 'd1616q2') comment.edit('New text') assert comment.body == 'New text'
def test_parent__submission(self): comment = Comment(self.reddit, 'cklfmye') with self.recorder.use_cassette('TestComment.test_parent__submission'): parent = comment.parent() assert comment in parent.comments assert isinstance(parent, Submission) assert parent.fullname == comment.parent_id
def test_enable_inbox_replies(self): self.reddit.read_only = False comment = Comment(self.reddit, "dcc9snh") with self.recorder.use_cassette( "TestComment.test_enable_inbox_replies" ): comment.enable_inbox_replies()
def test_parent__comment(self): comment = Comment(self.reddit, 'cklhv0f') with self.recorder.use_cassette('TestComment.test_parent__comment'): parent = comment.parent() parent.refresh() assert comment in parent.replies assert isinstance(parent, Comment) assert parent.fullname == comment.parent_id
def test_attributes(self): with self.recorder.use_cassette('TestComment.test_attributes'): comment = Comment(self.reddit, 'cklhv0f') assert comment.author == 'bboe' assert comment.body.startswith('Yes it does.') assert not comment.is_root assert comment.permalink(fast=True) == '/comments/2gmzqe//cklhv0f' assert comment.submission == '2gmzqe'
def test_reply(self): self.reddit.read_only = False with self.recorder.use_cassette('TestComment.test_reply'): parent_comment = Comment(self.reddit, 'd1616q2') comment = parent_comment.reply('Comment reply') assert comment.author == self.reddit.config.username assert comment.body == 'Comment reply' assert not comment.is_root assert comment.parent_id == parent_comment.fullname
def test_parent__chain(self): comment = Comment(self.reddit, 'dkk4qjd') counter = 0 with self.recorder.use_cassette('TestComment.test_parent__chain'): comment.refresh() parent = comment.parent() while parent != comment.submission: if counter % 9 == 0: parent.refresh() counter += 1 parent = parent.parent()
def test_id_from_url__invalid_urls(self): urls = ['', '1', '/', 'my.it/2gmzqe', 'http://my.it/_', 'https://redd.it/_/', 'http://reddit.com/comments/_/2gmzqe', 'http://my.it/2gmzqe', 'https://redd.it/2gmzqe', 'http://reddit.com/comments/2gmzqe', 'https://www.reddit.com/r/redditdev/comments/2gmzqe/'] for url in urls: with pytest.raises(ClientException): Comment.id_from_url(url)
def test_equality(self): comment1 = Comment(self.reddit, _data={'id': 'dummy1', 'n': 1}) comment2 = Comment(self.reddit, _data={'id': 'Dummy1', 'n': 2}) comment3 = Comment(self.reddit, _data={'id': 'dummy3', 'n': 2}) assert comment1 == comment1 assert comment2 == comment2 assert comment3 == comment3 assert comment1 == comment2 assert comment2 != comment3 assert comment1 != comment3 assert 'dummy1' == comment1 assert comment2 == 'dummy1'
def get_comment_stat(comment: Comment) -> dict: comment.refresh() comment.replies.replace_more(limit=0) result = {} result['comment_body'] = comment.body.replace('\n', '\\n') result['created_utc'] = datetime.fromtimestamp( comment.created_utc).strftime('%Y-%m-%d %H:%M') result['replies_count'] = len(comment.replies.list()) result['score'] = comment.score return result
def test_equality(self): comment1 = Comment(self.reddit, _data={"id": "dummy1", "n": 1}) comment2 = Comment(self.reddit, _data={"id": "Dummy1", "n": 2}) comment3 = Comment(self.reddit, _data={"id": "dummy3", "n": 2}) assert comment1 == comment1 assert comment2 == comment2 assert comment3 == comment3 assert comment1 == comment2 assert comment2 != comment3 assert comment1 != comment3 assert "dummy1" == comment1 assert comment2 == "dummy1"
def modify_exisiting_comment( comment: Comment, comment_string: str, post_tags: List[str] ) -> None: logger.debug(comment.body) if comment_string != comment.body: if len(post_tags) > 0: comment.edit(comment_string) logger.info(f"edited {comment_string}") else: comment.delete() logger.info(f"Comment deleted: {comment_string}") else: logger.info("Comment is the same as last time, not editing")
def replay_pending_tip(reddit, tx_queue, failover_time): # check if user have pending tips list_tips = user_function.get_unregistered_tip() if list_tips: for arr_tip in list_tips: tip = models.Tip().create_from_array(arr_tip) bot_logger.logger.info("replay tipping check for %s" % str(tip.id)) # check if it's not too old & replay tipping if not tip.is_expired(): if tip.receiver.is_registered(): bot_logger.logger.info( "replay tipping %s - %s send %s to %s " % ( str(tip.id), tip.sender.username, tip.amount, tip.receiver.username)) tip.tx_id = crypto.tip_user(tip.sender.address, tip.receiver.address, tip.amount, tx_queue, failover_time) if tip.tx_id: tip.finish = True user_function.remove_pending_tip(tip.id) if tip.message_fullname is not None: msg_id = re.sub(r't\d+_(?P<id>\w+)', r'\g<id>', tip.message_fullname) msg = Comment(reddit, msg_id) msg.reply(Template(lang.message_tip).render( sender=tip.sender.username, receiver=tip.receiver.username, amount=str(tip.amount), value_usd=str(tip.get_value_usd()), txid=tip.tx_id)) else: tip.status = "waiting registration of receiver" bot_logger.logger.info( "replay check for %s - user %s not registered " % (str(tip.id), tip.receiver.username)) else: tip.status = "receiver not registered in time" tip.finish = "" bot_logger.logger.info( "delete old tipping - %s send %s to %s " % ( tip.sender.username, tip.amount, tip.receiver.username)) user_function.remove_pending_tip(tip.id) # update tip status models.HistoryStorage.update_tip(tip.sender.username, tip) models.HistoryStorage.update_tip(tip.receiver.username, tip) else: bot_logger.logger.info("no pending tipping")
def replay_remove_pending_tip(rpc, reddit, tx_queue, failover_time): # check if it's not too old & replay tipping limit_date = datetime.datetime.now() - datetime.timedelta(days=3) # check if user have pending tips list_tips = user_function.get_unregistered_tip() if list_tips: for tip in list_tips: bot_logger.logger.info("replay tipping check for %s" % str(tip['id'])) if (datetime.datetime.strptime(tip['time'], '%Y-%m-%dT%H:%M:%S.%f') > limit_date): if (user_function.user_exist(tip['receiver'])): bot_logger.logger.info( "replay tipping %s - %s send %s to %s " % (str(tip['id']), tip['sender'], tip['amount'], tip['receiver'])) txid = crypto.tip_user(rpc, tip['sender'], tip['receiver'], tip['amount'], tx_queue, failover_time) user_function.remove_pending_tip(tip['id']) value_usd = utils.get_coin_value(tip['amount']) if 'message_fullname' in tip.keys(): msg_id = re.sub(r't\d+_(?P<id>\w+)', r'\g<id>', tip['message_fullname']) msg = Comment(reddit, msg_id) msg.reply( Template(lang.message_tip).render( sender=tip['sender'], receiver=tip['receiver'], amount=str(tip['amount']), value_usd=str(value_usd), txid=txid)) else: bot_logger.logger.info( "replay check for %s - user %s not registered " % (str(tip['id']), tip['receiver'])) else: bot_logger.logger.info( "delete old tipping - %s send %s for %s " % (tip['sender'], tip['amount'], tip['receiver'])) user_function.remove_pending_tip(tip['id']) else: bot_logger.logger.info("no pending tipping")
def on_comment(comment: models.Comment): try: parent = comment.parent() if type(parent) is models.Comment: # Did an uninfected person reply to an infected persons comment? if parent.author_flair_text and "INFECTED" in parent.author_flair_text and ( (comment.author_flair_text and "INFECTED" not in comment.author_flair_text) or not comment.author_flair_text): # infection! infect(comment, parent) else: # if type(parent) is models.Submission # Did an uninfected person reply to an infected persons submission? Roll dice for a 1 in 100 if parent.author_flair_text and "INFECTED" in parent.author_flair_text and ( (comment.author_flair_text and "INFECTED" not in comment.author_flair_text) or not comment.author_flair_text) and random.randint( 1, 100) == 69: infect(comment, parent) # if _debug: # print(comment) # TSV Format: Timestamp, Commentor Name, Commentor Comment ID, Commented on User, Commented on Item ID, Item Type, Commented on ?Infected? User _commentlog.write("{}\tu/{}\t{}\tu/{}\t{}\t{}\t{}\n".format( str(datetime.datetime.now()), comment.author.name, comment.id, "deleted" if not parent.author else parent.author.name, parent.id, "C" if type(parent) is models.Comment else "S", "I" if (parent.author_flair_text and "INFECTED" in parent.author_flair_text) else "N")) except Exception as ex: logger.info("ERROR IN ON_COMMENT") logger.info(str(ex)) pass
def test_id_from_url(self): urls = ['http://reddit.com/comments/2gmzqe/_/cklhv0f/', 'https://reddit.com/comments/2gmzqe/_/cklhv0f', 'http://www.reddit.com/r/redditdev/comments/2gmzqe/_/cklhv0f/', 'https://www.reddit.com/r/redditdev/comments/2gmzqe/_/cklhv0f'] for url in urls: assert Comment.id_from_url(url) == 'cklhv0f', url
def downvote_deleter(): reddit = get_reddit() redis_client = get_redis_client() logging.info('Monitoring downvotes') while True: for comment_id in redis_client.smembers('comments'): try: comment = Comment(reddit, id=comment_id.decode( 'utf-8')) # redis-py bug, not decoding to UTF-8 if comment.score < 1: comment.delete() redis_client.srem('comments', comment_id) logging.info(f'Removed downvoted comment {comment.id}') except praw.exceptions.PRAWException as e: logging.exception(e) time.sleep(60)
def test_refresh__deleted_comment(self): with self.recorder.use_cassette( 'TestComment.test_refresh__deleted_comment'): with pytest.raises(ClientException) as excinfo: Comment(self.reddit, 'd7ltvl0').refresh() assert ('This comment does not appear to be in the ' 'comment tree', ) == excinfo.value.args
def test_attributes(self): with self.recorder.use_cassette('TestComment.test_attributes'): comment = Comment(self.reddit, 'cklhv0f') assert comment.author == 'bboe' assert comment.body.startswith('Yes it does.') assert not comment.is_root assert comment.submission == '2gmzqe'
def test_refresh__with_reply_sort_and_limit(self): with self.recorder.use_cassette( "TestComment.test_refresh__with_reply_sort_and_limit" ): comment = Comment(self.reddit, "e4j4830") comment.reply_limit = 4 comment.reply_sort = "new" comment.refresh() replies = comment.replies last_created = float("inf") for reply in replies: if isinstance(reply, Comment): if reply.created_utc > last_created: assert False, "sort order incorrect" last_created = reply.created_utc assert len(comment.replies) == 3
def test_gild__no_creddits(self): self.reddit.read_only = False with self.recorder.use_cassette("TestComment.test_gild__no_creddits"): with pytest.raises(RedditAPIException) as excinfo: Comment(self.reddit, "d1616q2").gild() exception = excinfo.value assert "INSUFFICIENT_CREDDITS" == exception.error_type
def test_gild__no_creddits(self): self.reddit.read_only = False with self.recorder.use_cassette('TestComment.test_gild__no_creddits'): with pytest.raises(BadRequest) as excinfo: Comment(self.reddit, 'd1616q2').gild() reason = excinfo.value.response.json()['reason'] assert 'INSUFFICIENT_CREDDITS' == reason
def test_gild__no_creddits(self): self.reddit.read_only = False with self.recorder.use_cassette("TestComment.test_gild__no_creddits"): with pytest.raises(BadRequest) as excinfo: Comment(self.reddit, "d1616q2").gild() reason = excinfo.value.response.json()["reason"] assert "INSUFFICIENT_CREDDITS" == reason
def test_attributes(self): with self.recorder.use_cassette("TestComment.test_attributes"): comment = Comment(self.reddit, "cklhv0f") assert comment.author == "bboe" assert comment.body.startswith("Yes it does.") assert not comment.is_root assert comment.submission == "2gmzqe"
def test_refresh__removed_comment(self): with self.recorder.use_cassette( "TestComment.test_refresh__removed_comment"): with pytest.raises(ClientException) as excinfo: Comment(self.reddit, "dma3mi5").refresh() assert ("This comment does not appear to be in the comment tree", ) == excinfo.value.args
def test_comment_no_has_url(self): comment = Comment( reddit, url= "https://www.reddit.com/r/worldnews/comments/98aj0i/former_un_chief_kofi_annan_dies_at_80/e4en2bt/", ) assert find_urls_in(comment) is None
def test_award__not_enough_coins(self): self.reddit.read_only = False with self.use_cassette(): with pytest.raises(RedditAPIException) as excinfo: Comment(self.reddit, "g7cmlgc").award( gild_type="award_2385c499-a1fb-44ec-b9b7-d260f3dc55de") exception = excinfo.value assert "INSUFFICIENT_COINS_WITH_AMOUNT" == exception.error_type
def test_award__self_gild(self): self.reddit.read_only = False with self.recorder.use_cassette("TestComment.test_award__self_gild"): with pytest.raises(RedditAPIException) as excinfo: Comment(self.reddit, "g7cn9xb").award( gild_type="award_2385c499-a1fb-44ec-b9b7-d260f3dc55de") exception = excinfo.value assert "SELF_GILDING_NOT_ALLOWED" == exception.error_type
def test_id_from_url__invalid_urls(self): urls = [ "", "1", "/", "my.it/2gmzqe", "http://my.it/_", "https://redd.it/_/", "http://reddit.com/comments/_/2gmzqe", "http://my.it/2gmzqe", "https://redd.it/2gmzqe", "http://reddit.com/comments/2gmzqe", "https://www.reddit.com/r/redditdev/comments/2gmzqe/", ] for url in urls: with pytest.raises(ClientException): Comment.id_from_url(url)
def run(self): for cid in self.cids: author = Comment(self.reddit, id=cid).author try: self.authors.append('Null' if author is None or author.created_utc > self.dateline else author.name) except: self.authors.append('NULL-ERR') self.i += 1
def safe_comment_reply(self, comment: Comment, text_body: str): """ Attempts to reply to a comment & safely handles a RedditAPIException (e.g. if that comment has been deleted & cannot be responded to) Attributes: comment: a praw Comment model instance text_body: the markdown text to include in the reply made """ try: comment.reply(body=text_body) except RedditAPIException as redditErr: tprint(f"Unable to reply (RedditAPIException): {redditErr}") return None except Exception as err: tprint(f"Unable to reply (general Exception): {err}") return None
def test_construct_failure(self): message = "Exactly one of `id`, `url`, or `_data` must be provided." with pytest.raises(TypeError) as excinfo: Comment(self.reddit) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, id="dummy", url="dummy") assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, "dummy", _data={"id": "dummy"}) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, url="dummy", _data={"id": "dummy"}) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, "dummy", "dummy", {"id": "dummy"}) assert str(excinfo.value) == message with pytest.raises(ValueError): Comment(self.reddit, "") with pytest.raises(ValueError): Comment(self.reddit, url="")
def test_id_from_url(self): urls = [ "http://reddit.com/comments/2gmzqe/_/cklhv0f/", "https://reddit.com/comments/2gmzqe/_/cklhv0f", "http://www.reddit.com/r/redditdev/comments/2gmzqe/_/cklhv0f/", "https://www.reddit.com/r/redditdev/comments/2gmzqe/_/cklhv0f", ] for url in urls: assert Comment.id_from_url(url) == "cklhv0f", url
def should_respond(self, comment: Comment) -> bool: if not isinstance(comment.parent(), Submission): return False if not re.findall(r'([A-Z]{1,2}[0-9]{4}\-?[A-Za-z0-9]*\:\ *\w+)', comment.body or ""): return False return comment.submission.link_flair_text in [ submission_types.EK_STEMMING, submission_types.TK_STEMMING, submission_types.EK_TK_STEMMING ]
def test_comment_has_url(self): comment = Comment( reddit, url= "https://www.reddit.com/r/worldnews/comments/986846/ukraine_demands_15_year_sentence_for_ousted/e4dqaw1/", ) assert find_urls_in(comment) == [ "https://www.businessinsider.com/paul-manafort-daughter-text-messages-ukraine-2017-3" ]
def remove_post(reddit: Reddit, comment: Comment, message: str, mod_note: str, note_message: str, strike: bool): comment.parent().edit(message + f'\n\n{config["suffix"]}') comment.submission.mod.remove(spam=False, mod_note=mod_note) c.execute('DELETE FROM pendingposts WHERE submission_id=?', (comment.submission.id, )) conn.commit() # Time to update the usernotes... if strike: print("Updating usernotes...") usernotespage = reddit.subreddit(config['subreddit']).wiki["usernotes"] usernotescontent = json.loads(usernotespage.content_md) usernotes = decode_blob(usernotescontent['blob']) username = comment.submission.author.name mod_number = usernotescontent['constants']['users'].index( 'Enslaved_Horny_AI') if username in usernotes: usernotes[username]['ns'].append({ 'l': f'l,{comment.submission.id}', 'm': mod_number, 'n': note_message, 't': int(time.time()), 'w': 0 }) else: usernotes[username] = { 'ns': [{ 'l': f'l,{comment.submission.id}', 'm': mod_number, 'n': note_message, 't': int(time.time()), 'w': 0 }] } usernotescontent["blob"] = encode_blob(usernotes) usernotespage.edit( content=json.dumps(usernotescontent, separators=(',', ':'))) print('User notes updated.')
def reply_to_comment(self, comment_id: Text, comment_body: Text, subreddit: Text = None) -> Optional[Comment]: if self.live_response: return self._reply_to_comment(comment_id, comment_body, subreddit=subreddit) log.debug('Live response disabled') # TODO - 1/12/2021 - Sketchy at best return Comment(self.reddit.reddit, id='1111')
def test_construct_failure(self): message = 'Exactly one of `id`, `url`, or `_data` must be provided.' with pytest.raises(TypeError) as excinfo: Comment(self.reddit) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, id='dummy', url='dummy') assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, 'dummy', _data={'id': 'dummy'}) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, url='dummy', _data={'id': 'dummy'}) assert str(excinfo.value) == message with pytest.raises(TypeError) as excinfo: Comment(self.reddit, 'dummy', 'dummy', {'id': 'dummy'}) assert str(excinfo.value) == message
def test_permalink(self): with self.recorder.use_cassette('TestComment.test_permalink'): comment = Comment(self.reddit, 'cklhv0f') assert comment.permalink() == ('/r/redditdev/comments/2gmzqe/' 'praw_https_enabled_praw_testing_' 'needed/cklhv0f')
def test_disable_inbox_replies(self): self.reddit.read_only = False comment = Comment(self.reddit, 'dcc9snh') with self.recorder.use_cassette( 'TestComment.test_disable_inbox_replies'): comment.disable_inbox_replies()
def test_edit(self, _): self.reddit.read_only = False with self.recorder.use_cassette("TestComment.test_edit"): comment = Comment(self.reddit, "d1616q2") comment.edit("New text") assert comment.body == "New text"