示例#1
0
    def _send_private_message(self,
                              user: Redditor,
                              message_body,
                              subject: Text = 'Repost Check',
                              source: Text = None,
                              post_id: Text = None,
                              comment_id: Text = None) -> NoReturn:

        if not user:
            log.error('No user provided to send private message')
            return
        try:
            start_time = perf_counter()
            user.message(subject, message_body)
            self._record_api_event(
                float(round(perf_counter() - start_time, 2)),
                'private_message', self.reddit.reddit.auth.limits['remaining'])
            log.info('Sent PM to %s. ', user.name)
        except Exception as e:
            log.exception('Failed to send PM to %s', user.name, exc_info=True)
            raise

        self._save_private_message(
            BotPrivateMessage(subject=subject,
                              body=message_body,
                              in_response_to_post=post_id,
                              in_response_to_comment=comment_id,
                              triggered_from=source,
                              recipient=user.name))
示例#2
0
    def test_construct_failure(self):
        message = 'Either `name` or `_data` must be provided.'
        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit)
        assert str(excinfo.value) == message

        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit, 'dummy', {'id': 'dummy'})
        assert str(excinfo.value) == message
示例#3
0
 def test_hash(self):
     redditor1 = Redditor(self.reddit, _data={'name': 'dummy1', 'n': 1})
     redditor2 = Redditor(self.reddit, _data={'name': 'Dummy1', 'n': 2})
     redditor3 = Redditor(self.reddit, _data={'name': 'dummy3', 'n': 2})
     assert hash(redditor1) == hash(redditor1)
     assert hash(redditor2) == hash(redditor2)
     assert hash(redditor3) == hash(redditor3)
     assert hash(redditor1) == hash(redditor2)
     assert hash(redditor2) != hash(redditor3)
     assert hash(redditor1) != hash(redditor3)
示例#4
0
 def test_hash(self):
     redditor1 = Redditor(self.reddit, _data={"name": "dummy1", "n": 1})
     redditor2 = Redditor(self.reddit, _data={"name": "Dummy1", "n": 2})
     redditor3 = Redditor(self.reddit, _data={"name": "dummy3", "n": 2})
     assert hash(redditor1) == hash(redditor1)
     assert hash(redditor2) == hash(redditor2)
     assert hash(redditor3) == hash(redditor3)
     assert hash(redditor1) == hash(redditor2)
     assert hash(redditor2) != hash(redditor3)
     assert hash(redditor1) != hash(redditor3)
示例#5
0
def reddit_activity(username: str):
    """Requests comment and submission data for the given user and any other users they have interacted with.
       Interactions between users are when the given user has replied to a submission or comment by another user.
       Writes data to out/{username}.csv.
    """
    reddit = Reddit(client_id=config.client_id,
                    client_secret=config.client_secret,
                    user_agent=config.user_agent)

    # Build queue of users to collect activity of: provided user and users they have interacted via replying
    # Also append users who have interacted with provided user (they replied to a post/comment)
    users = exactlyOnceQueue()
    users.append(username)
    redditor = Redditor(reddit, name=username)

    for comment in redditor.comments.new():
        if comment.parent().author:
            users.append(str(comment.parent().author))
        # Add users who have replied to this comment
        for reply in comment.replies:
            if reply.author:
                users.append(str(reply.author))


    for submission in redditor.submissions.new():
        # Add users who have replied to this submission
        for reply in submission.comments:
            if reply.author:
                users.append(str(reply.author))



    # Get comment and submission data of each user and append to list
    data = []
    print(f'users to process:{str(len(users))}')
    while len(users) > 0:
        redditor = Redditor(reddit, name=users.pop()) # type: Redditor
        try:
            for submission in redditor.submissions.new(): # type: Submission
                row = parse_submission(submission)
                data.append(row)
            for comment in redditor.comments.new(): # type: Comment
                row = parse_comment(comment)
                data.append(row)
        except exceptions.NotFound:
            print(f'Exception occured on user {str(redditor)}')
        except exceptions.Forbidden:
            print(f'Exception occured on user {str(redditor)}')
        print(f'user complete, remaining = {str(len(users))}')

    # Construct DataFrame from list and write to CSV
    df = pandas.DataFrame(data=data, columns=['id', 'author', 'date', 'subreddit', 'replyingTo', 'polarity', 'subjectivity', 'replyCount'])
    df.set_index('id', inplace=True)
    df.to_csv(f'out/{username}.csv')
示例#6
0
 def test_equality(self):
     redditor1 = Redditor(self.reddit, _data={"name": "dummy1", "n": 1})
     redditor2 = Redditor(self.reddit, _data={"name": "Dummy1", "n": 2})
     redditor3 = Redditor(self.reddit, _data={"name": "dummy3", "n": 2})
     assert redditor1 == redditor1
     assert redditor2 == redditor2
     assert redditor3 == redditor3
     assert redditor1 == redditor2
     assert redditor2 != redditor3
     assert redditor1 != redditor3
     assert "dummy1" == redditor1
     assert redditor2 == "dummy1"
示例#7
0
 def test_equality(self):
     redditor1 = Redditor(self.reddit, _data={'name': 'dummy1', 'n': 1})
     redditor2 = Redditor(self.reddit, _data={'name': 'Dummy1', 'n': 2})
     redditor3 = Redditor(self.reddit, _data={'name': 'dummy3', 'n': 2})
     assert redditor1 == redditor1
     assert redditor2 == redditor2
     assert redditor3 == redditor3
     assert redditor1 == redditor2
     assert redditor2 != redditor3
     assert redditor1 != redditor3
     assert 'dummy1' == redditor1
     assert redditor2 == 'dummy1'
示例#8
0
    def test_construct_failure(self):
        message = "Exactly one of `name`, `fullname`, or `_data` must be provided."
        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit)
        assert str(excinfo.value) == message

        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit, "dummy", _data={"id": "dummy"})
        assert str(excinfo.value) == message

        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit, name="dummy", fullname="t2_dummy")
        assert str(excinfo.value) == message

        with pytest.raises(TypeError) as excinfo:
            Redditor(
                self.reddit,
                name="dummy",
                fullname="t2_dummy",
                _data={"id": "dummy"},
            )
        assert str(excinfo.value) == message

        with pytest.raises(AssertionError):
            Redditor(self.reddit, _data=[{"name": "dummy"}])

        with pytest.raises(AssertionError):
            Redditor(self.reddit, _data={"notname": "dummy"})

        with pytest.raises(ValueError):
            Redditor(self.reddit, "")
        with pytest.raises(ValueError):
            Redditor(self.reddit, fullname="")
示例#9
0
    def test_construct_failure(self):
        message = "Either `name` or `_data` must be provided."
        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit)
        assert str(excinfo.value) == message

        with pytest.raises(TypeError) as excinfo:
            Redditor(self.reddit, "dummy", {"id": "dummy"})
        assert str(excinfo.value) == message

        with pytest.raises(AssertionError):
            Redditor(self.reddit, _data=[{"name": "dummy"}])

        with pytest.raises(AssertionError):
            Redditor(self.reddit, _data={"notname": "dummy"})
示例#10
0
 def test_remove_invite__redditor(self):
     self.reddit.read_only = False
     thread = LiveThread(self.reddit, "xyu8kmjvfrww")
     redditor = Redditor(self.reddit, _data={"name": "nmtake", "id": "ll32z"})
     with self.recorder.use_cassette(
         "TestLiveContributorRelationship_test_remove_invite__redditor"
     ):
         thread.contributor.remove_invite(redditor)
示例#11
0
 def test__params_not_modified_in_mixed_listing(self):
     params = {"dummy": "value"}
     redditor = Redditor(self.reddit, name="spez")
     for listing in ["controversial", "hot", "new", "top"]:
         generator = getattr(redditor, listing)(params=params)
         assert params == {"dummy": "value"}
         assert listing == generator.params["sort"]
         assert "value" == generator.params["dummy"]
示例#12
0
 def test__params_not_modified_in_mixed_listing(self):
     params = {'dummy': 'value'}
     redditor = Redditor(self.reddit, name='spez')
     for listing in ['controversial', 'hot', 'new', 'top']:
         generator = getattr(redditor, listing)(params=params)
         assert params == {'dummy': 'value'}
         assert listing == generator.params['sort']
         assert 'value' == generator.params['dummy']
示例#13
0
 def test_remove__redditor(self):
     self.reddit.read_only = False
     thread = LiveThread(self.reddit, "xyu8kmjvfrww")
     redditor = Redditor(self.reddit,
                         _data={
                             "name": "nmtake",
                             "id": "ll32z"
                         })
     with self.use_cassette():
         thread.contributor.remove(redditor)
示例#14
0
文件: test_live.py 项目: zed7576/praw
 def test_remove_invite__redditor(self):
     self.reddit.read_only = False
     thread = LiveThread(self.reddit, 'xyu8kmjvfrww')
     redditor = Redditor(self.reddit,
                         _data={
                             'name': 'nmtake',
                             'id': 'll32z'
                         })
     with self.recorder.use_cassette('TestLiveContributorRelationship_'
                                     'test_remove_invite__redditor'):
         thread.contributor.remove_invite(redditor)
示例#15
0
 def test_repr(self):
     redditor = Redditor(self.reddit, name="RedditorName")
     assert repr(redditor) == "Redditor(name='RedditorName')"
示例#16
0
 def test_pickle(self):
     redditor = Redditor(self.reddit, _data={"name": "name", "id": "dummy"})
     for level in range(pickle.HIGHEST_PROTOCOL + 1):
         other = pickle.loads(pickle.dumps(redditor, protocol=level))
         assert redditor == other
def CreateRedditor(user_name: str):
    reddit = praw.Reddit("scraper_tool", user_agent='Python 3.8')
    return Redditor(reddit, user_name)
示例#18
0
 def test_guild__max(self):
     with pytest.raises(TypeError) as excinfo:
         Redditor(self.reddit, name="RedditorName").gild(37)
     assert str(excinfo.value) == "months must be between 1 and 36"
示例#19
0
 def test_fullname(self):
     redditor = Redditor(self.reddit, _data={"name": "name", "id": "dummy"})
     assert redditor.fullname == "t2_dummy"
示例#20
0
 def test_fullname(self):
     redditor = Redditor(self.reddit, _data={'name': 'name', 'id': 'dummy'})
     assert redditor.fullname == 't2_dummy'
示例#21
0
 def test_str(self):
     redditor = Redditor(self.reddit, _data={'name': 'name', 'id': 'dummy'})
     assert str(redditor) == 'name'
示例#22
0
 def test_repr(self):
     redditor = Redditor(self.reddit, name='RedditorName')
     assert repr(redditor) == 'Redditor(name=\'RedditorName\')'
示例#23
0
def gold(reddit, msg, tx_queue, failover_time):
    user = models.User(msg.author.name)
    if user.is_registered():
        gold_month = number_gold_credit()

        if msg.body.strip() == 'buy':
            # Number of month
            quantity = 1

            # check if we have enough credits
            if not gold_month >= quantity:
                # store in db want an gold, when bot have new credits a PM can be send
                db = TinyDB(config.DATA_PATH + 'reddit_gold_empty.json')
                db.insert({
                    "user": user.username,
                    "quantity": quantity,
                    'time': datetime.datetime.now().isoformat(),
                })
                db.close()

                msg.reply(Template(lang.message_gold_no_more).render(username=user.username))
                return False

            # check user confirmed balance is ok
            if user.get_balance_confirmed() >= config.price_reddit_gold:
                msg.reply(Template(lang.message_gold_no_enough_pivx).render(username=user.username))
                return False

            # send amount of one month of gold to address
            tx_id = crypto.tip_user(user.address, config.gold_address, config.price_reddit_gold, tx_queue,
                                    failover_time)

            if tx_id:
                # send gold reddit
                Redditor(reddit, user.username).gild(months=quantity)

                # update gold reddit table
                store_user_buy(user, quantity, tx_id)

                # update user history
                models.HistoryStorage.add_to_history(user, sender=user.username, receiver="Reddit",
                                                     amount=config.price_reddit_gold,
                                                     action="buy reddit gold")

                # send succes message
                msg.reply(Template(lang.message_buy_gold_success).render(username=user.username))
            else:
                # send error message
                msg.reply(Template(lang.message_buy_gold_error).render(username=user.username))

        elif msg.body.strip() == 'remind':
            # store in db want an gold, when bot have new credits a PM can be send
            db = TinyDB(config.DATA_PATH + 'reddit_gold_remind.json')
            db.insert({
                "user": user.username,
                "remind": "True",
                'time': datetime.datetime.now().isoformat(),
            })
            db.close()

        else:
            # send info on reddit gold
            msg.reply(Template(lang.message_buy_gold).render(username=user.username, gold_credit=gold_month,
                                                             price=config.price_reddit_gold))
    else:
        bot_logger.logger.info('user %s not registered (command : donate) ' % user.username)
        msg.reply(Template(lang.message_need_register + lang.message_footer).render(username=user.username))
示例#24
0
def a_user(wsb_reddit_client) -> Redditor:
    yield Redditor(wsb_reddit_client.reddit, name='WSBTickerBotHandler')
示例#25
0
 def test_guild__min(self):
     with pytest.raises(TypeError) as excinfo:
         Redditor(self.reddit, name='RedditorName').gild(0)
     assert str(excinfo.value) == 'months must be between 1 and 36'
示例#26
0
 def test_str(self):
     redditor = Redditor(self.reddit, _data={"name": "name", "id": "dummy"})
     assert str(redditor) == "name"
示例#27
0
 def test_pickle(self):
     redditor = Redditor(self.reddit, _data={'name': 'name', 'id': 'dummy'})
     for level in range(pickle.HIGHEST_PROTOCOL + 1):
         other = pickle.loads(pickle.dumps(redditor, protocol=level))
         assert redditor == other
示例#28
0
async def on_message(message):
    server = message.server
    author = message.author
    name = get_disc_name(author)

    if message.channel.id == config.VERIFICATION_CHANNEL and message.content.startswith(
            "!verify"):
        logging.debug("Verify started by {}".format(name))
        arguments = message.content.split(" ")

        if len(arguments) < 2:
            await log("No URL from %user%", author)
            await answer(message, "Usage: !verify <cckufi comment url>")
            return

        if name in discord_blacklist:
            await log(
                "Blacklisted discord user %user% just tried to register!",
                author)
            await answer(message, "Invalid URL!")
            return

        raw_url = arguments[1]
        url = url_fix(raw_url)

        if not url.startswith(config.POST_URL):
            await log("Invalid URL from %user%", author)
            await answer(message, "Invalid URL!")
            return

        comment_id = Comment.id_from_url(url)
        logging.debug("Reading comment {}".format(comment_id))

        comment = get_comment(comment_id)

        if comment is None:
            await log(
                "User %user% linked comment {} which does not exist".format(
                    comment_id), author)
            await answer(message, "that comment does not exist!")
            return

        reddit_user = comment.author
        reddit_name = reddit_user.name

        if reddit_name in reddit_blacklist:
            await log(
                "Blacklisted reddit user {} (discord %user%) just tried to register!"
                .format(reddit_name), author)
            await answer(
                message, "that comment does not just contain your discord ID!")
            return

        comment_body = comment.body

        if comment_body.startswith(name):

            # Check CoT submissions
            members, joined, betrayed = analyze_circle_flair(
                reddit, reddit_user, cot)

            if not members:
                await log(
                    "Denied discord user %user% (reddit {}), they haven't posted on CoT"
                    .format(reddit_name), author)
                await answer(
                    message,
                    "you must have posted or commented on /r/CircleofTrust to be verified."
                )
                return

            if betrayed:
                await log(
                    "Denied discord user %user% (reddit {}), they have betrayed!"
                    .format(reddit_name), author)
                await answer(
                    message,
                    "you have betrayed {} times! Please ask for manual verification."
                    .format(joined))
                return

            await client.change_nickname(author, "/u/{}".format(reddit_name))
            await client.add_roles(author, verified_role)
            await log("Verified %user%, member of {} circles".format(joined),
                      author)
            await answer(message, "you have been successfully verified!")
        else:
            await log(
                "Comment does not start with their discord ID: {}, got '{}' instead."
                .format(url, comment_body))
            await answer(message,
                         "that comment does not start with your discord ID!")

    elif message.content.startswith("!flair"):
        logging.debug("Circle command ran by {}".format(name))

        arguments = message.content.split(" ")

        if len(arguments) < 2:
            await answer(message, "Usage !circles <reddit user>")
            return

        logging.info(arguments[1])

        reddit_name = arguments[1]

        # Check for discord mentions
        discord_id = re.search(r"<@!(\d{17})>", arguments[1])

        if discord_id:
            discord_user = server.get_member(discord_id.group(1))
            logging.info(discord_user)
            if discord_user:
                reddit_name = discord_user.name
                logging.info(reddit_name)

        reddit_name = re.sub(r"(@?/?u/)", "", reddit_name)
        reddit_user = Redditor(reddit, name=reddit_name)

        members, joined, betrayed = analyze_circle_flair(
            reddit, reddit_user, cot)

        if not members:
            await log(
                "Lookup by %user% for {} failed, they haven't posted on CoT".
                format(reddit_name), author)
            await answer(message,
                         "that user has not posted on /r/CircleofTrust.")
            return

        await log("Lookup by %user% for {}.".format(reddit_name), author)
        await answer(
            message, "Users in circle: {}, member of circles: {}".format(
                members, joined) + (" BETRAYER!" if betrayed else ""))
    return