def handle(self, *args, **options): for comment_id in preloaded_explore_comment_ids(): comment = QuestComment.objects.get(id=comment_id) author = comment.author print author.username Actions.featured_in_explore(author, comment, defer=False) economy.credit(author, knobs.REWARDS['featured_in_explore'])
def test_expander_honors_unsubscribe_per_channel(self): author = utils.create_user() comment = utils.create_comment() comment.author = author comment.save() self.assertEqual(comment.thread.op.author, author) another_user = utils.create_user() pn = Actions.replied(another_user, comment) notifications = expander.expand(pn) self.assertTrue(notifications) notification = filter(lambda n: n.channel == 'EmailChannel', notifications)[0] self.assertEqual(author, notification.recipient) # Now, let the user unsubscribe to the reply action. author.kv.subscriptions.unsubscribe('thread_replied') pn = Actions.replied(another_user, comment) notifications = expander.expand(pn) recipients = [ n.recipient for n in notifications if n.channel == 'EmailChannel' ] self.assertFalse(author in recipients)
def followee_posted(): Actions.followee_posted(author, comment) #TODO this should happen because of the above Actions.followee_posted for follower_id in author.redis.new_followers.zrange(0, -1): RealtimeChannel('user:{}:rt_tab_badges'.format(follower_id), 1).publish({'tab_badge_update': 'home'})
def level_up(user, only_once=True): from canvas.notifications.actions import Actions from canvas import last_sticker reward_stickers = 0 while user.kv.sticker_inbox.get() >= sticker_schedule(user.kv.sticker_level.get()): sticker_level = user.kv.sticker_level.get() result = user.kv.sticker_inbox.increment_ifsufficient(-sticker_schedule(sticker_level)) # If there weren't actually enough, the user was already rewarded in a different request. Update their # sticker data. if not result['success']: user_kv = user.redis.user_kv.hgetall() break user.kv.sticker_level.increment() reward = sticker_schedule(user.kv.sticker_level.get(), reward=True) user.kv.stickers.currency.increment(reward) reward_stickers += reward user_kv = user.redis.user_kv.hgetall() Actions.leveled_up(user, reward) if only_once: break if reward_stickers: realtime_update_sticker_counts(user) last_sticker.realtime_update_sticker_receipt(user) return reward_stickers
def follow(self, user_to_follow): if self == user_to_follow: raise ValueError("Can't follow self.") from canvas.notifications.actions import Actions Actions.followed_by_user(self, user_to_follow) self.redis.following.sadd(user_to_follow.id) user_to_follow.redis.followers.sadd(self.id)
def notify_followers_of_signup(self, access_token, access_token_secret): from canvas.models import FriendJoinedNotificationReceipt if self.user is None: raise ValueError("This TwitterUser instance isn't yet associated with a DrawQuest User.") followers = self.followers_on_drawquest(access_token, access_token_secret) Actions.twitter_friend_joined(self.user, followers) FriendJoinedNotificationReceipt.create_receipts_in_bulk(self.user, [follower.user for follower in followers])
def grant_daily_free_stickers(user, force=False, count=knobs.DAILY_FREE_STICKERS): from canvas.notifications.actions import Actions if not user.is_authenticated(): return if not force and not eligible_for_daily_free_stickers(user): return user.kv.daily_free_timestamp.set(time.time()) user.kv.has_unseen_daily_free_stickers.set(True) user.kv.stickers.currency.increment(count) Actions.daily_free_stickers(user, count)
def notify_followers_of_signup(self, access_token, access_token_secret): from canvas.models import FriendJoinedNotificationReceipt if self.user is None: raise ValueError( "This TwitterUser instance isn't yet associated with a DrawQuest User." ) followers = self.followers_on_drawquest(access_token, access_token_secret) Actions.twitter_friend_joined(self.user, followers) FriendJoinedNotificationReceipt.create_receipts_in_bulk( self.user, [follower.user for follower in followers])
def invite(self, inviter, invitees, type='invite', ignore_errors=False): if not ignore_errors: for invitee in invitees: if invitee.id in self: raise ServiceError("User {} has already been invited.".format(invitee.username)) if invitee.id == inviter.id: raise ServiceError("You can't invite yourself - you're already here!") if self.quest.author == invitee: raise ServiceError("That user is already in this quest.") self.sadd([invitee.id for invitee in invitees]) for invitee in invitees: Actions.invite_user(inviter, self.quest, invitee) invitee.redis.quest_invites.add_invite(self.quest)
def test_replied_tells_author_and_op_author(self): # Some dude starts a thread author = create_user() content = create_content() op = create_comment(author=author, reply_content=content) # Another dude posts a reply guest_author = create_user() reply = create_comment(replied_comment=op, author=guest_author, parent_comment=op) self.assertEqual(reply.thread.op, op) # A third dude replies to the guest author guest_author_2 = create_user() reply_2 = create_comment(replied_comment=reply, author=guest_author_2, parent_comment=op) self.assertTrue(reply_2.thread.op.author, author) # Issue the action pn = Actions.replied(guest_author_2, reply_2) notifications = expander.expand(pn) print notifications # Now, we should tell both the OP author, and the guest author. notifications = filter(lambda n: n.channel == 'EmailChannel', notifications) self.assertEqual(len(notifications), 2) n1 = notifications[0] n2 = notifications[1] self.assertEqual(n1.action, 'replied') self.assertEqual(n1.recipient, guest_author) self.assertEqual(n2.action, 'thread_replied') self.assertEqual(n2.recipient, author)
def test_user_receives(self): user = utils.create_user() pn = Actions.daily_free_stickers(user, 5) ex = expander.get_expander(pn)() recipients = ex.decide_recipients(pn) self.assertEqual(len(recipients), 1) self.assertIn(user, recipients)
def test_digest_expander(self): user = create_user() pn = Actions.digest(user) notifications = expander.expand(pn) self.assertEqual(len(notifications), 1) notification = notifications.pop() self.assertEqual(notification.recipient, user)
def test_24h_digest_email(self): user = create_user(email="*****@*****.**") pn = Actions.digest(user) notification = Notification.from_pending_notification(pn, user, "EmailChannel") email_message = EmailChannel().make_message(notification, force=True) message = EmailChannel().make_email_backend_message(email_message) email_message.record_sent(notification.action)
def test_Notification_from_pn(self): pn = Actions.replied(create_user(), create_comment()) notification = Notification.from_pending_notification(pn, create_user, "EmailChannel") assert notification.recipient for key in pn.data: self.assertEqual(getattr(notification, key), getattr(pn, key)) assert pn.comment assert notification.comment
def invite(self, inviter, invitees, type='invite', ignore_errors=False): if not ignore_errors: for invitee in invitees: if invitee.id in self: raise ServiceError( "User {} has already been invited.".format( invitee.username)) if invitee.id == inviter.id: raise ServiceError( "You can't invite yourself - you're already here!") if self.quest.author == invitee: raise ServiceError("That user is already in this quest.") self.sadd([invitee.id for invitee in invitees]) for invitee in invitees: Actions.invite_user(inviter, self.quest, invitee) invitee.redis.quest_invites.add_invite(self.quest)
def follow(self, user_to_follow): from canvas.notifications.actions import Actions if self == user_to_follow: raise ValueError("Can't follow self.") if user_to_follow.id in self.redis.new_following: return self.redis.following.sadd(user_to_follow.id) self.redis.new_following.bump(user_to_follow.id) user_to_follow.redis.followers.sadd(self.id) user_to_follow.redis.new_followers.bump(self.id) Actions.followed_by_user(self, user_to_follow) user_to_follow.userinfo.refresh_follower_count() self._followed_or_unfollowed()
def test_delivering_email_records_email_sent_metric(self): with override_service('experiment_placer', FakeExperimentPlacer, kwargs={'email_notifications': 'experimental'}): user = create_user(email="*****@*****.**") comment = create_comment() comment2 = create_comment(author=user, replied_comment=comment) pn = Actions.replied(user, comment2) notification = Notification.from_pending_notification(pn, user, "EmailChannel") channel = EmailChannel() with override_service('metrics', FakeMetrics): channel.deliver(notification) self.assertEqual(1, len(Services.metrics.email_sent.records))
def test_replied_to_own_thread_does_not_email_self(self): user = create_user() comment = create_comment(author=user) assert comment.author == user reply = create_comment(replied_comment=comment) assert comment == reply.replied_comment pn = Actions.replied(user, reply) notifications = expander.expand(pn) recipients = [n.recipient for n in notifications] self.assertNotIn(user, recipients)
def test_expander_honors_unsubscribe_per_channel(self): author = utils.create_user() comment = utils.create_comment() comment.author = author comment.save() self.assertEqual(comment.thread.op.author, author) another_user = utils.create_user() pn = Actions.replied(another_user, comment) notifications = expander.expand(pn) self.assertTrue(notifications) notification = filter(lambda n: n.channel == 'EmailChannel', notifications)[0] self.assertEqual(author, notification.recipient) # Now, let the user unsubscribe to the reply action. author.kv.subscriptions.unsubscribe('thread_replied') pn = Actions.replied(another_user, comment) notifications = expander.expand(pn) recipients = [n.recipient for n in notifications if n.channel == 'EmailChannel'] self.assertFalse(author in recipients)
def test_notifies_author(self): author = utils.create_user() comment = utils.create_comment() comment.author = author comment.save() another_user = utils.create_user() comment_sticker = CommentSticker(comment=comment, type_id=stickers.get("num1").type_id, timestamp=time.time(), ip="127.0.0.1", user=another_user) pn = Actions.stickered(another_user, comment_sticker) ex = expander.get_expander(pn)() recipients = ex.decide_recipients(pn) self.assertEqual(len(recipients), 1) self.assertIn(author, recipients)
def test_op_author_expander_notifies_author(self): author = utils.create_user() comment = utils.create_comment() comment.author = author comment.save() self.assertEqual(comment.thread.op.author, author) another_user = utils.create_user() pn = Actions.replied(another_user, comment) replied_expander = expander.get_expander(pn)() notifications = replied_expander.expand(pn) recipients = [n.recipient for n in notifications] #self.assertEqual(len(recipients), 1) self.assertIn(author, recipients)
def test_replied_op_only_tells_author(self): author = create_user() content = create_content() op = create_comment(author=author, reply_content=content) user = create_user() reply = create_comment(replied_comment=op, author=user) self.assertEqual(reply.replied_comment, op) pn = Actions.replied(user, reply) notifications = expander.expand(pn) for n in notifications: print n self.assertEqual(len(filter(lambda n: n.channel == 'EmailChannel', notifications)), 1) notification = notifications.pop() # Note that it will be 'replied', not 'thread_replied'. The former is more specific. self.assertEqual(notification.action, 'replied')
def test_user_can_unsubscribe_through_header_link(self): user = create_user(email="*****@*****.**") comment = create_comment() comment2 = create_comment(author=user, replied_comment=comment) pn = Actions.replied(user, comment2) notification = Notification.from_pending_notification(pn, user, "EmailChannel") email_message = EmailChannel().make_message(notification, force=True) message = EmailChannel().make_email_backend_message(email_message) email_message.record_sent(notification.action) assert message.extra_headers unsubscribe_link = message.extra_headers.get("List-Unsubscribe") assert unsubscribe_link # Use should be able to receive notifications ... self.assertTrue(user.kv.subscriptions.can_receive('replied')) # Now, 'curl' the unsubscribe link self.assertStatus(200, unsubscribe_link) # Now, this action should be disabled in the notifications subscriptions. self.assertFalse(user.kv.subscriptions.can_receive('replied'))
def test_user_can_unsubscribe_through_header_link(self): user = create_user(email="*****@*****.**") comment = create_comment() comment2 = create_comment(author=user, replied_comment=comment) pn = Actions.replied(user, comment2) notification = Notification.from_pending_notification(pn, user, "EmailChannel") email_message = EmailChannel().make_message(notification, force=True) message = EmailChannel().make_email_backend_message(email_message) email_message.record_sent(notification.action) assert message.extra_headers unsubscribe_link = message.extra_headers.get("List-Unsubscribe") assert unsubscribe_link # Use should be able to receive notifications ... self.assertTrue(user.kv.subscriptions.can_receive("replied")) # Now, 'curl' the unsubscribe link self.assertStatus(200, unsubscribe_link) # Now, this action should be disabled in the notifications subscriptions. self.assertFalse(user.kv.subscriptions.can_receive("replied"))
def followee_posted(): Actions.followee_posted(author, comment)
def playback_action(): Actions.playback(instance.viewer, instance.comment)
def test_newsletter_expander_for_user_with_no_email(self): user = create_user(email="") pn = Actions.newsletter(user) self.assertFalse(user.email) notifications = expander.expand(pn) self.assertEqual(len(notifications), 0)
def get_email_message(): user = create_user() pn = Actions.digest(user) notification = Notification.from_pending_notification(pn, user, "EmailChannel") return EmailChannel().make_message(notification, force=True)
def followee_posted(): Actions.followee_posted(author, comment) # TODO this should happen because of the above Actions.followee_posted for follower_id in author.redis.new_followers.zrange(0, -1): RealtimeChannel("user:{}:rt_tab_badges".format(follower_id), 1).publish({"tab_badge_update": "home"})
def do_notify(): Actions.replied(request.user, comment)
def followee_created_ugq(): Actions.followee_created_ugq(author, quest)