From 3ba65af19e731ede4bbe3ecfa7d33debfd400565 Mon Sep 17 00:00:00 2001 From: Vikhyat Korrapati Date: Tue, 17 Jun 2014 11:59:49 +0530 Subject: [PATCH] Add like-based system badges. --- app/jobs/regular/update_badges.rb | 17 +++++++++++++++++ app/models/post_action.rb | 20 +++++++++++++------- app/services/badge_granter.rb | 7 +++++-- config/locales/client.en.yml | 12 ++++++++++++ db/fixtures/601_badges.rb | 27 +++++++++++++++++++++++++++ spec/services/badge_granter_spec.rb | 24 ++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 9 deletions(-) diff --git a/app/jobs/regular/update_badges.rb b/app/jobs/regular/update_badges.rb index ba33ce6c275..3432b02e676 100644 --- a/app/jobs/regular/update_badges.rb +++ b/app/jobs/regular/update_badges.rb @@ -21,5 +21,22 @@ module Jobs end end + def post_like(args) + post = Post.find(args[:post_id]) + user = post.user + + # Grant "Welcome" badge to the user if they do not already have it. + BadgeGranter.grant(Badge.find(5), user) + + [{id: 6, count: 10}, {id: 7, count: 25}, {id: 8, count: 100}].each do |b| + if post.like_count >= b[:count] + BadgeGranter.grant(Badge.find(b[:id]), user, post_id: post.id) + else + user_badge = UserBadge.find_by(badge_id: b[:id], user_id: user.id, post_id: post.id) + user_badge && BadgeGranter.revoke(user_badge) + end + end + end + end end diff --git a/app/models/post_action.rb b/app/models/post_action.rb index 7aab8f6ea9e..86dcf78d814 100644 --- a/app/models/post_action.rb +++ b/app/models/post_action.rb @@ -131,13 +131,19 @@ class PostAction < ActiveRecord::Base post.topic.posts_count != 1 end - create( post_id: post.id, - user_id: user.id, - post_action_type_id: post_action_type_id, - message: opts[:message], - staff_took_action: opts[:take_action] || false, - related_post_id: related_post_id, - targets_topic: !!targets_topic ) + post_action = create( post_id: post.id, + user_id: user.id, + post_action_type_id: post_action_type_id, + message: opts[:message], + staff_took_action: opts[:take_action] || false, + related_post_id: related_post_id, + targets_topic: !!targets_topic ) + + if post_action && post_action.is_like? + BadgeGranter.update_badges(action: :post_like, post_id: post.id) + end + + post_action rescue ActiveRecord::RecordNotUnique # can happen despite being .create diff --git a/app/services/badge_granter.rb b/app/services/badge_granter.rb index baa759daadf..b132c7af184 100644 --- a/app/services/badge_granter.rb +++ b/app/services/badge_granter.rb @@ -3,6 +3,7 @@ class BadgeGranter def initialize(badge, user, opts={}) @badge, @user, @opts = badge, user, opts @granted_by = opts[:granted_by] || Discourse.system_user + @post_id = opts[:post_id] end def self.grant(badge, user, opts={}) @@ -12,12 +13,14 @@ class BadgeGranter def grant return if @granted_by and !Guardian.new(@granted_by).can_grant_badges?(@user) - user_badge = UserBadge.find_by(badge_id: @badge.id, user_id: @user.id) + user_badge = UserBadge.find_by(badge_id: @badge.id, user_id: @user.id, post_id: @post_id) if user_badge.nil? || @badge.multiple_grant? UserBadge.transaction do user_badge = UserBadge.create!(badge: @badge, user: @user, - granted_by: @granted_by, granted_at: Time.now) + granted_by: @granted_by, + granted_at: Time.now, + post_id: @post_id) if @granted_by != Discourse.system_user StaffActionLogger.new(@granted_by).log_badge_grant(user_badge) diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index d10cb8fe7a1..de108327829 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1927,3 +1927,15 @@ en: elder: name: Elder description: Granted global edit, pin, close, archive, split and merge. + welcome: + name: Welcome + description: Received a like. + nice_post: + name: Nice Post + description: Received 10 likes on a post. + good_post: + name: Good Post + description: Received 25 likes on a post. + great_post: + name: Great Post + description: Received 100 likes on a post. diff --git a/db/fixtures/601_badges.rb b/db/fixtures/601_badges.rb index 4e16c48a2d4..e4479ffc860 100644 --- a/db/fixtures/601_badges.rb +++ b/db/fixtures/601_badges.rb @@ -1,3 +1,4 @@ +# Trust level system badges. trust_level_badges = [ {id: 1, name: "Basic User", type: 3}, {id: 2, name: "Regular User", type: 3}, @@ -44,3 +45,29 @@ SQL Badge.where(id: Badge.trust_level_badge_ids).each {|badge| badge.reset_grant_count! } end +# +# Like system badges. +like_badges = [ + {id: 5, name: "Welcome", type: 3, multiple: false}, + {id: 6, name: "Nice Post", type: 3, multiple: true}, + {id: 7, name: "Good Post", type: 2, multiple: true}, + {id: 8, name: "Great Post", type: 1, multiple: true} +] + +like_badges.each do |spec| + Badge.seed do |b| + b.id = spec[:id] + b.name = spec[:name] + b.badge_type_id = spec[:type] + b.multiple_grant = spec[:multiple] + end +end + +# Create an example badge if one does not already exist. +if Badge.find_by(id: 101).nil? + Badge.seed do |b| + b.id = 101 + b.name = "Example Badge" + b.badge_type_id = 3 + end +end diff --git a/spec/services/badge_granter_spec.rb b/spec/services/badge_granter_spec.rb index 8c8efaf1b3c..f893bd42cf6 100644 --- a/spec/services/badge_granter_spec.rb +++ b/spec/services/badge_granter_spec.rb @@ -72,6 +72,7 @@ describe BadgeGranter do context "update_badges" do let(:user) { Fabricate(:user) } + let(:liker) { Fabricate(:user) } it "grants and revokes trust level badges" do user.change_trust_level!(:elder) @@ -80,6 +81,29 @@ describe BadgeGranter do UserBadge.where(user_id: user.id, badge_id: 1).first.should_not be_nil UserBadge.where(user_id: user.id, badge_id: 2).first.should be_nil end + + it "grants system like badges" do + post = create_post(user: user) + # Welcome badge + PostAction.act(liker, post, PostActionType.types[:like]) + UserBadge.find_by(user_id: user.id, badge_id: 5).should_not be_nil + # Nice post badge + post.update_attributes like_count: 10 + BadgeGranter.update_badges(action: :post_like, post_id: post.id) + UserBadge.find_by(user_id: user.id, badge_id: 6).should_not be_nil + # Good post badge + post.update_attributes like_count: 25 + BadgeGranter.update_badges(action: :post_like, post_id: post.id) + UserBadge.find_by(user_id: user.id, badge_id: 7).should_not be_nil + # Great post badge + post.update_attributes like_count: 100 + BadgeGranter.update_badges(action: :post_like, post_id: post.id) + UserBadge.find_by(user_id: user.id, badge_id: 8).should_not be_nil + # Revoke badges on unlike + post.update_attributes like_count: 99 + BadgeGranter.update_badges(action: :post_like, post_id: post.id) + UserBadge.find_by(user_id: user.id, badge_id: 8).should be_nil + end end end