FEATURE: Generous badge

This commit is contained in:
Robin Ward 2016-03-15 16:06:50 -04:00
parent cfe18c3f5b
commit 06591022fe
9 changed files with 57 additions and 7 deletions

View file

@ -75,9 +75,13 @@ class ApplicationController < ActionController::Base
render 'default/empty'
end
def render_rate_limit_error(e)
render_json_error e.description, type: :rate_limit, status: 429
end
# If they hit the rate limiter
rescue_from RateLimiter::LimitExceeded do |e|
render_json_error e.description, type: :rate_limit, status: 429
render_rate_limit_error(e)
end
rescue_from PG::ReadOnlySqlTransaction do |e|

View file

@ -23,6 +23,15 @@ class PostActionsController < ApplicationController
@post.reload
render_post_json(@post, _add_raw = false)
end
rescue RateLimiter::LimitExceeded => e
# Special case: if we hit the create like rate limit, record it in user history
# so we can award a badge
if e.type == "create_like"
UserHistory.create!(action: UserHistory.actions[:rate_limited_like],
target_user_id: current_user.id,
post_id: @post.id)
end
render_rate_limit_error(e)
end
def destroy

View file

@ -28,6 +28,7 @@ class Badge < ActiveRecord::Base
FamousLink = 30
Admired = 31
GivesBack = 32
Generous = 33
# other consts
AutobiographerMinBioLength = 10
@ -218,6 +219,14 @@ SQL
HAVING us.likes_given::float / count(*) > 5.0
SQL
Generous = <<-SQL
SELECT uh.target_user_id AS user_id, MIN(uh.created_at) AS granted_at
FROM user_histories AS uh
WHERE uh.action = #{UserHistory.actions[:rate_limited_like]}
AND (:backfill OR uh.target_user_id IN (:user_ids))
GROUP BY uh.target_user_id
SQL
def self.invite_badge(count,trust_level)
"
SELECT u.id user_id, current_timestamp granted_at

View file

@ -51,7 +51,8 @@ class UserHistory < ActiveRecord::Base
revoke_admin: 33,
grant_moderation: 34,
revoke_moderation: 35,
backup_operation: 36)
backup_operation: 36,
rate_limited_like: 37)
end
# Staff actions is a subset of all actions, used to audit actions taken by staff users.

View file

@ -2970,6 +2970,9 @@ en:
gives_back:
name: Gives Back
description: Has a high ratio of likes given to likes received
generous:
name: Generous
description: Used the maximum amount of likes in a day
google_search: |
<h3>Search with Google</h3>

View file

@ -316,6 +316,18 @@ Badge.seed do |b|
b.system = true
end
Badge.seed do |b|
b.id = Badge::Generous
b.default_name = "Generous"
b.default_icon = "fa-heart"
b.badge_type_id = BadgeType::Silver
b.query = Badge::Queries::Generous
b.default_badge_grouping_id = BadgeGrouping::Community
b.trigger = Badge::Trigger::None
b.auto_revoke = false
b.system = true
end
Badge.where("NOT system AND id < 100").each do |badge|
new_id = [Badge.maximum(:id) + 1, 100].max
old_id = badge.id

View file

@ -2,6 +2,7 @@ class RateLimiter
# A rate limit has been exceeded.
class LimitExceeded < StandardError
attr_reader :type
def initialize(available_in, type=nil)
@available_in = available_in

View file

@ -94,10 +94,6 @@ describe RateLimiter do
end
end
end
end

View file

@ -7,7 +7,22 @@ describe PostActionsController do
expect { xhr :post, :create }.to raise_error(Discourse::NotLoggedIn)
end
describe 'logged in' do
describe 'logged in as regular user' do
before do
@user = log_in(:user)
@post = Fabricate(:post, user: Fabricate(:coding_horror))
end
it 'creates user history if the rate limit for a like is hit' do
PostAction.expects(:act).once.raises(RateLimiter::LimitExceeded.new(60, 'create_like'))
expect(-> {
xhr :post, :create, id: @post.id, post_action_type_id: PostActionType.types[:like]
puts response.success?
}).to change(UserHistory, :count).by(1)
end
end
describe 'logged in as moderator' do
before do
@user = log_in(:moderator)
@post = Fabricate(:post, user: Fabricate(:coding_horror))