FEATURE: New "First Onebox" badge

This commit is contained in:
Robin Ward 2016-04-12 14:09:59 -04:00
parent 04c1d37e63
commit 0396b14b70
No known key found for this signature in database
GPG Key ID: 0E091E2B4ED1B83D
9 changed files with 55 additions and 7 deletions

View File

@ -16,6 +16,7 @@ class Badge < ActiveRecord::Base
FirstQuote = 15 FirstQuote = 15
FirstMention = 40 FirstMention = 40
FirstEmoji = 41 FirstEmoji = 41
FirstOnebox = 42
ReadGuidelines = 16 ReadGuidelines = 16
Reader = 17 Reader = 17

View File

@ -5,6 +5,11 @@ class PostAnalyzer
def initialize(raw, topic_id) def initialize(raw, topic_id)
@raw = raw @raw = raw
@topic_id = topic_id @topic_id = topic_id
@found_oneboxes = false
end
def found_oneboxes?
@found_oneboxes
end end
# What we use to cook posts # What we use to cook posts
@ -12,6 +17,7 @@ class PostAnalyzer
cooked = PrettyText.cook(*args) cooked = PrettyText.cook(*args)
result = Oneboxer.apply(cooked, topic_id: @topic_id) do |url, _| result = Oneboxer.apply(cooked, topic_id: @topic_id) do |url, _|
@found_oneboxes = true
Oneboxer.invalidate(url) if args.last[:invalidate_oneboxes] Oneboxer.invalidate(url) if args.last[:invalidate_oneboxes]
Oneboxer.cached_onebox url Oneboxer.cached_onebox url
end end

View File

@ -2974,7 +2974,11 @@ en:
first_mention: first_mention:
name: First Mention name: First Mention
description: Mentioned a user in a Post description: Mentioned a user in a Post
long_description: This badge is granted the first time you mention someone's @username in your post. Each mention generates a notification to that person, so they know about your post. Just begin typing `@` to mention any user or (if allowed) group it's a convenient way to bring something to their attention. long_description: This badge is granted the first time you mention someone's @username in your post. Each mention generates a notification to that person, so they know about your post. Just begin typing `@` to mention any user or (if allowed) group it's a convenient way to bring something to their attention.
first_onebox:
name: First Onebox
description: Posted a link that was oneboxed
long_description: This badge is granted when you post a link which is expanded with extra information.
admin_login: admin_login:
success: "Email Sent" success: "Email Sent"

View File

@ -386,6 +386,20 @@ Badge.seed do |b|
b.system = true b.system = true
end end
Badge.seed do |b|
b.id = Badge::FirstOnebox
b.default_name = "First Onebox"
b.badge_type_id = BadgeType::Bronze
b.multiple_grant = false
b.target_posts = true
b.show_posts = true
b.query = nil
b.badge_grouping_id = BadgeGrouping::GettingStarted
b.default_badge_grouping_id = BadgeGrouping::GettingStarted
b.trigger = Badge::Trigger::PostProcessed
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

View File

@ -17,7 +17,10 @@ class CookedPostProcessor
@cooking_options = post.cooking_options || opts[:cooking_options] || {} @cooking_options = post.cooking_options || opts[:cooking_options] || {}
@cooking_options[:topic_id] = post.topic_id @cooking_options[:topic_id] = post.topic_id
@cooking_options = @cooking_options.symbolize_keys @cooking_options = @cooking_options.symbolize_keys
@doc = Nokogiri::HTML::fragment(post.cook(post.raw, @cooking_options))
analyzer = post.post_analyzer
@doc = Nokogiri::HTML::fragment(analyzer.cook(post.raw, @cooking_options))
@has_oneboxes = analyzer.found_oneboxes?
@size_cache = {} @size_cache = {}
end end
@ -46,9 +49,8 @@ class CookedPostProcessor
def grant_badges def grant_badges
return unless Guardian.new.can_see?(@post) return unless Guardian.new.can_see?(@post)
if has_emoji? BadgeGranter.grant(Badge.find(Badge::FirstEmoji), @post.user) if has_emoji?
BadgeGranter.grant(Badge.find(Badge::FirstEmoji), @post.user) BadgeGranter.grant(Badge.find(Badge::FirstOnebox), @post.user) if @has_oneboxes
end
end end
def keep_reverse_index_up_to_date def keep_reverse_index_up_to_date
@ -286,6 +288,7 @@ class CookedPostProcessor
# apply oneboxes # apply oneboxes
Oneboxer.apply(@doc, topic_id: @post.topic_id) { |url| Oneboxer.apply(@doc, topic_id: @post.topic_id) { |url|
@has_oneboxes = true
Oneboxer.onebox(url, args) Oneboxer.onebox(url, args)
} }

View File

@ -96,7 +96,6 @@ module Oneboxer
changed = false changed = false
Oneboxer.each_onebox_link(doc) do |url, element| Oneboxer.each_onebox_link(doc) do |url, element|
if args && args[:topic_id] if args && args[:topic_id]
url = append_source_topic_id(url, args[:topic_id]) url = append_source_topic_id(url, args[:topic_id])
end end

View File

@ -488,6 +488,7 @@ describe CookedPostProcessor do
end end
context "grant badges" do context "grant badges" do
context "emoji inside a quote" do context "emoji inside a quote" do
let(:post) { Fabricate(:post, raw: "time to eat some sweet [quote]:candy:[/quote] mmmm") } let(:post) { Fabricate(:post, raw: "time to eat some sweet [quote]:candy:[/quote] mmmm") }
let(:cpp) { CookedPostProcessor.new(post) } let(:cpp) { CookedPostProcessor.new(post) }
@ -507,6 +508,23 @@ describe CookedPostProcessor do
expect(post.user.user_badges.where(badge_id: Badge::FirstEmoji).exists?).to eq(true) expect(post.user.user_badges.where(badge_id: Badge::FirstEmoji).exists?).to eq(true)
end end
end end
context "onebox" do
let(:user) { Fabricate(:user) }
let(:post) { Fabricate.build(:post, user: user, raw: "onebox me:\n\nhttps://www.youtube.com/watch?v=Wji-BZ0oCwg\n") }
let(:cpp) { CookedPostProcessor.new(post) }
before do
Oneboxer.stubs(:onebox)
end
it "awards a badge for using an emoji" do
cpp.post_process_oneboxes
cpp.grant_badges
expect(post.user.user_badges.where(badge_id: Badge::FirstOnebox).exists?).to eq(true)
end
end
end end
end end

View File

@ -17,6 +17,7 @@ describe PostAnalyzer do
it 'fetches the cached onebox for any urls in the post' do it 'fetches the cached onebox for any urls in the post' do
Oneboxer.expects(:cached_onebox).with url Oneboxer.expects(:cached_onebox).with url
post_analyzer.cook(*args) post_analyzer.cook(*args)
expect(post_analyzer.found_oneboxes?).to be(true)
end end
it 'does not invalidate the onebox cache' do it 'does not invalidate the onebox cache' do
@ -153,6 +154,8 @@ describe PostAnalyzer do
it "finds links from HTML" do it "finds links from HTML" do
post_analyzer = PostAnalyzer.new(raw_post_two_links_html, default_topic_id) post_analyzer = PostAnalyzer.new(raw_post_two_links_html, default_topic_id)
post_analyzer.cook(raw_post_two_links_html, {})
expect(post_analyzer.found_oneboxes?).to be(false)
expect(post_analyzer.link_count).to eq(2) expect(post_analyzer.link_count).to eq(2)
end end
end end

View File

@ -221,7 +221,7 @@ describe PostAlerter do
create_post(topic_id: topic.id, user: user, raw: "my magic topic\n##{Discourse.base_url}#{post1.url}") create_post(topic_id: topic.id, user: user, raw: "my magic topic\n##{Discourse.base_url}#{post1.url}")
user.reload user.reload
expect(user.notifications.count).to eq(1) expect(user.notifications.where(notification_type: Notification.types[:linked]).count).to eq(1)
expect(watcher.notifications.count).to eq(1) expect(watcher.notifications.count).to eq(1)