mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-05-03 01:15:48 -04:00
FEATURE: Generous badge
This commit is contained in:
parent
cfe18c3f5b
commit
06591022fe
9 changed files with 57 additions and 7 deletions
app
config/locales
db/fixtures
lib/rate_limiter
spec
|
@ -75,9 +75,13 @@ class ApplicationController < ActionController::Base
|
||||||
render 'default/empty'
|
render 'default/empty'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_rate_limit_error(e)
|
||||||
|
render_json_error e.description, type: :rate_limit, status: 429
|
||||||
|
end
|
||||||
|
|
||||||
# If they hit the rate limiter
|
# If they hit the rate limiter
|
||||||
rescue_from RateLimiter::LimitExceeded do |e|
|
rescue_from RateLimiter::LimitExceeded do |e|
|
||||||
render_json_error e.description, type: :rate_limit, status: 429
|
render_rate_limit_error(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue_from PG::ReadOnlySqlTransaction do |e|
|
rescue_from PG::ReadOnlySqlTransaction do |e|
|
||||||
|
|
|
@ -23,6 +23,15 @@ class PostActionsController < ApplicationController
|
||||||
@post.reload
|
@post.reload
|
||||||
render_post_json(@post, _add_raw = false)
|
render_post_json(@post, _add_raw = false)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Badge < ActiveRecord::Base
|
||||||
FamousLink = 30
|
FamousLink = 30
|
||||||
Admired = 31
|
Admired = 31
|
||||||
GivesBack = 32
|
GivesBack = 32
|
||||||
|
Generous = 33
|
||||||
|
|
||||||
# other consts
|
# other consts
|
||||||
AutobiographerMinBioLength = 10
|
AutobiographerMinBioLength = 10
|
||||||
|
@ -218,6 +219,14 @@ SQL
|
||||||
HAVING us.likes_given::float / count(*) > 5.0
|
HAVING us.likes_given::float / count(*) > 5.0
|
||||||
SQL
|
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)
|
def self.invite_badge(count,trust_level)
|
||||||
"
|
"
|
||||||
SELECT u.id user_id, current_timestamp granted_at
|
SELECT u.id user_id, current_timestamp granted_at
|
||||||
|
|
|
@ -51,7 +51,8 @@ class UserHistory < ActiveRecord::Base
|
||||||
revoke_admin: 33,
|
revoke_admin: 33,
|
||||||
grant_moderation: 34,
|
grant_moderation: 34,
|
||||||
revoke_moderation: 35,
|
revoke_moderation: 35,
|
||||||
backup_operation: 36)
|
backup_operation: 36,
|
||||||
|
rate_limited_like: 37)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Staff actions is a subset of all actions, used to audit actions taken by staff users.
|
# Staff actions is a subset of all actions, used to audit actions taken by staff users.
|
||||||
|
|
|
@ -2970,6 +2970,9 @@ en:
|
||||||
gives_back:
|
gives_back:
|
||||||
name: Gives Back
|
name: Gives Back
|
||||||
description: Has a high ratio of likes given to likes received
|
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: |
|
google_search: |
|
||||||
<h3>Search with Google</h3>
|
<h3>Search with Google</h3>
|
||||||
|
|
|
@ -316,6 +316,18 @@ Badge.seed do |b|
|
||||||
b.system = true
|
b.system = true
|
||||||
end
|
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|
|
Badge.where("NOT system AND id < 100").each do |badge|
|
||||||
new_id = [Badge.maximum(:id) + 1, 100].max
|
new_id = [Badge.maximum(:id) + 1, 100].max
|
||||||
old_id = badge.id
|
old_id = badge.id
|
||||||
|
|
|
@ -2,6 +2,7 @@ class RateLimiter
|
||||||
|
|
||||||
# A rate limit has been exceeded.
|
# A rate limit has been exceeded.
|
||||||
class LimitExceeded < StandardError
|
class LimitExceeded < StandardError
|
||||||
|
attr_reader :type
|
||||||
|
|
||||||
def initialize(available_in, type=nil)
|
def initialize(available_in, type=nil)
|
||||||
@available_in = available_in
|
@available_in = available_in
|
||||||
|
|
|
@ -94,10 +94,6 @@ describe RateLimiter do
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,22 @@ describe PostActionsController do
|
||||||
expect { xhr :post, :create }.to raise_error(Discourse::NotLoggedIn)
|
expect { xhr :post, :create }.to raise_error(Discourse::NotLoggedIn)
|
||||||
end
|
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
|
before do
|
||||||
@user = log_in(:moderator)
|
@user = log_in(:moderator)
|
||||||
@post = Fabricate(:post, user: Fabricate(:coding_horror))
|
@post = Fabricate(:post, user: Fabricate(:coding_horror))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue