Key:
nuotm=New User of The Month
Introduction
New User of The Month is a badge that discourse grants to users with “outstanding contributions in their first month” but, this badge is very rigged.
Here is the code that discourse runs to grant nuotm
If you can't access that
# frozen_string_literal: true
module Jobs
class GrantNewUserOfTheMonthBadges < ::Jobs::Scheduled
every 1.day
MAX_AWARDED = 2
def execute(args)
badge = Badge.find(Badge::NewUserOfTheMonth)
return unless SiteSetting.enable_badges? && badge.enabled?
previous_month_beginning = 1.month.ago.beginning_of_month
previous_month_end = 1.month.ago.end_of_month
if UserBadge.where(
"badge_id = ? AND granted_at BETWEEN ? AND ?",
badge.id,
previous_month_beginning,
Time.zone.now,
).exists?
return
end
scores(previous_month_beginning, previous_month_end).each do |user_id, score|
# Don't bother awarding to users who haven't received any likes
if score > 0.0
user = User.find(user_id)
if user.badges.where(id: Badge::NewUserOfTheMonth).blank?
BadgeGranter.grant(badge, user, created_at: previous_month_end)
SystemMessage.new(user).create(
"new_user_of_the_month",
month_year: I18n.l(previous_month_beginning, format: :no_day),
url: "#{Discourse.base_url}/badges",
)
end
end
end
end
def scores(min_user_created_at, max_user_created_at)
current_owners = UserBadge.where(badge_id: Badge::NewUserOfTheMonth).pluck(:user_id)
current_owners = [-1] if current_owners.blank?
# Find recent accounts and come up with a score based on how many likes they
# received, based on how much they posted and how old the accounts of the people
# who voted on them are.
sql = <<~SQL
SELECT u.id,
SUM(CASE
WHEN pa.id IS NOT NULL THEN
CASE
WHEN liked_by.id <= 0 THEN 0.0
WHEN liked_by.admin THEN 3.0
WHEN liked_by.moderator THEN 3.0
WHEN liked_by.trust_level = 4 THEN 2.0
WHEN liked_by.trust_level = 3 THEN 1.5
WHEN liked_by.trust_level = 2 THEN 1.0
WHEN liked_by.trust_level = 1 THEN 0.25
WHEN liked_by.trust_level = 0 THEN 0.1
ELSE 1.0
END
ELSE 0
END) / (5 + COUNT(DISTINCT p.id))::float AS score
FROM users AS u
INNER JOIN user_stats AS us ON u.id = us.user_id
LEFT OUTER JOIN posts AS p ON p.user_id = u.id
LEFT OUTER JOIN post_actions AS pa ON pa.post_id = p.id AND pa.post_action_type_id = #{PostActionType.types[:like]}
LEFT OUTER JOIN users AS liked_by ON liked_by.id = pa.user_id
LEFT OUTER JOIN topics AS t ON t.id = p.topic_id
WHERE u.active
AND u.id > 0
AND u.id NOT IN (#{current_owners.join(",")})
AND NOT u.staged
AND NOT u.admin
AND NOT u.moderator
AND u.suspended_at IS NULL
AND u.suspended_till IS NULL
AND u.created_at BETWEEN :min_user_created_at AND :max_user_created_at
AND t.archetype <> '#{Archetype.private_message}'
AND t.deleted_at IS NULL
AND p.deleted_at IS NULL
GROUP BY u.id
HAVING COUNT(DISTINCT p.id) > 1
AND COUNT(DISTINCT p.topic_id) > 1
AND COUNT(pa.id) > 1
ORDER BY score DESC
LIMIT #{MAX_AWARDED}
SQL
Hash[
*DB.query_single(
sql,
min_user_created_at: min_user_created_at,
max_user_created_at: max_user_created_at,
)
]
end
end
end
Now, look at this user
0 likes received, 0 given, 0 posts created
And they got nuotm.
In the code there is this:
“Don’t bother awarding to users who haven’t received any likes”
Hmm…
[WIP, adding more soon]