docbrown/app/labor/badge_rewarder.rb

107 lines
4.8 KiB
Ruby

module BadgeRewarder
YEARS = { 1 => "one", 2 => "two", 3 => "three", 4 => "four", 5 => "five", 6 => "six", 7 => "seven", 8 => "eight", 9 => "nine", 10 => "ten" }.freeze
def self.award_yearly_club_badges
(1..3).each do |i|
message = "Happy DEV birthday! Can you believe it's been #{i} #{'year'.pluralize(i)} already?!"
badge = Badge.find_by(slug: "#{YEARS[i]}-year-club")
User.where("created_at < ? AND created_at > ?", i.year.ago, i.year.ago - 2.days).find_each do |user|
achievement = BadgeAchievement.create(
user_id: user.id,
badge_id: badge.id,
rewarding_context_message_markdown: message,
)
user.save if achievement.valid?
end
end
end
def self.award_beloved_comment_badges
Comment.where("positive_reactions_count > ?", 24).find_each do |comment|
message = "You're DEV famous! [This is the comment](https://dev.to#{comment.path}) for which you are being recognized. 😄"
achievement = BadgeAchievement.create(
user_id: comment.user_id,
badge_id: Badge.find_by(slug: "beloved-comment")&.id || 3,
rewarding_context_message_markdown: message,
)
comment.user.save if achievement.valid?
# ID 3 is the proper ID in prod. We should change in future to ENV var.
end
end
def self.award_top_seven_badges(usernames, message_markdown = "Congrats!!!")
award_badges(usernames, "top-7", message_markdown)
end
def self.award_fab_five_badges(usernames, message_markdown = "Congrats!!!")
award_badges(usernames, "fab-5", message_markdown)
end
def self.award_contributor_badges(usernames, message_markdown = "Thank you so much for your contributions!")
award_badges(usernames, "dev-contributor", message_markdown)
end
def self.award_tag_badges
Tag.where.not(badge_id: nil).find_each do |tag|
past_winner_user_ids = BadgeAchievement.where(badge_id: tag.badge_id).pluck(:user_id)
winning_article = Article.where("score > 100").
published.
where.not(user_id: past_winner_user_ids).
order("score DESC").
where("published_at > ?", 7.5.days.ago). # More than seven days, to have some wiggle room.
cached_tagged_with(tag).first
if winning_article
award_badges(
[winning_article.user.username],
tag.badge.slug,
"Congratulations on posting the most beloved [##{tag.name}](#{ApplicationConfig['APP_PROTOCOL'] + ApplicationConfig['APP_DOMAIN']}/t/#{tag.name}) post from the past seven days! Your winning post was [#{winning_article.title}](#{ApplicationConfig['APP_PROTOCOL'] + ApplicationConfig['APP_DOMAIN'] + winning_article.path}). (You can only win once per badge-eligible tag)",
)
end
end
end
def self.award_contributor_badges_from_github(since = 1.day.ago, message_markdown = "Thank you so much for your contributions!")
client = Octokit::Client.new
badge = Badge.find_by(slug: "dev-contributor")
["thepracticaldev/dev.to", "thepracticaldev/DEV-ios", "thepracticaldev/DEV-Android"].each do |repo|
commits = client.commits repo, since: since.iso8601
authors_uids = commits.map { |commit| commit.author.id }
Identity.where(provider: "github", uid: authors_uids).find_each do |i|
BadgeAchievement.where(user_id: i.user_id, badge_id: badge.id).first_or_create(
rewarding_context_message_markdown: message_markdown,
)
end
end
end
def self.award_streak_badge(num_weeks)
article_user_ids = Article.published.where("published_at > ? AND score > ?", 1.week.ago, -25).pluck(:user_id) # No cred for super low quality
message = if num_weeks == 16
"16 weeks! You've achieved the longest DEV writing streak possible. This makes you eligible for special quests in the future. Keep up the amazing contributions to our community!"
else
"Congrats on achieving this streak! Consistent writing is hard. The next streak badge you can get is the #{num_weeks * 2} Week Badge. 😉"
end
users = User.where(id: article_user_ids).where("articles_count >= ?", num_weeks)
usernames = []
users.find_each do |user|
count = 0
num_weeks.times do |i|
num = i + 1
count += 1 if user.articles.published.where("published_at > ? AND published_at < ?", num.weeks.ago, (num - 1).weeks.ago).any?
end
usernames << user.username if count >= num_weeks
end
award_badges(usernames, "#{num_weeks}-week-streak", message)
end
def self.award_badges(usernames, slug, message_markdown)
User.where(username: usernames).find_each do |user|
BadgeAchievement.create(
user_id: user.id,
badge_id: Badge.find_by(slug: slug).id,
rewarding_context_message_markdown: message_markdown,
)
user.save
end
end
end