diff --git a/lib/onebox/engine/discourse_local_onebox.rb b/lib/onebox/engine/discourse_local_onebox.rb new file mode 100644 index 00000000000..d67eb706df7 --- /dev/null +++ b/lib/onebox/engine/discourse_local_onebox.rb @@ -0,0 +1,84 @@ +module Onebox + module Engine + class DiscourseLocalOnebox + include Engine + + matches_regexp Regexp.new("^#{Discourse.base_url.gsub(".","\\.")}.*$", true) + + def to_html + uri = URI::parse(@url) + route = Rails.application.routes.recognize_path(uri.path) + + args = {original_url: @url} + + # Figure out what kind of onebox to show based on the URL + case route[:controller] + when 'topics' + + linked = "#{@url}" + if route[:post_number].present? && route[:post_number].to_i > 1 + # Post Link + post = Post.where(topic_id: route[:topic_id], post_number: route[:post_number].to_i).first + return linked unless post + return linked unless Guardian.new.can_see?(post) + + topic = post.topic + slug = Slug.for(topic.title) + + excerpt = post.excerpt(SiteSetting.post_onebox_maxlength) + excerpt.gsub!("\n"," ") + # hack to make it render for now + excerpt.gsub!("[/quote]", "[quote]") + quote = "[quote=\"#{post.user.username}, topic:#{topic.id}, slug:#{slug}, post:#{post.post_number}\"]#{excerpt}[/quote]" + + cooked = PrettyText.cook(quote) + return cooked + + else + # Topic Link + topic = Topic.where(id: route[:topic_id].to_i).includes(:user).first + return linked unless topic + return linked unless Guardian.new.can_see?(topic) + + post = topic.posts.first + + posters = topic.posters_summary.map do |p| + { + username: p[:user].username, + avatar: PrettyText.avatar_img(p[:user].avatar_template, 'tiny'), + description: p[:description], + extras: p[:extras] + } + end + + category = topic.category + if category + category = "#{category.name}" + end + + quote = post.excerpt(SiteSetting.post_onebox_maxlength) + args.merge! title: topic.title, + avatar: PrettyText.avatar_img(topic.user.avatar_template, 'tiny'), + posts_count: topic.posts_count, + last_post: FreedomPatches::Rails4.time_ago_in_words(topic.last_posted_at, false, scope: :'datetime.distance_in_words_verbose'), + age: FreedomPatches::Rails4.time_ago_in_words(topic.created_at, false, scope: :'datetime.distance_in_words_verbose'), + views: topic.views, + posters: posters, + quote: quote, + category: category, + topic: topic.id + + @template = 'topic' + end + + end + + return nil unless @template + Mustache.render(File.read("#{Rails.root}/lib/onebox/templates/discourse_#{@template}_onebox.handlebars"), args) + rescue ActionController::RoutingError + nil + end + + end + end +end diff --git a/lib/onebox/templates/discourse_topic_onebox.handlebars b/lib/onebox/templates/discourse_topic_onebox.handlebars new file mode 100644 index 00000000000..e61c7871582 --- /dev/null +++ b/lib/onebox/templates/discourse_topic_onebox.handlebars @@ -0,0 +1,20 @@ + diff --git a/lib/oneboxer.rb b/lib/oneboxer.rb index 6b6f3dc5473..7c9b3923719 100644 --- a/lib/oneboxer.rb +++ b/lib/oneboxer.rb @@ -1,3 +1,8 @@ + +Dir["#{Rails.root}/lib/onebox/engine/*_onebox.rb"].each {|f| + require_dependency(f.split('/')[-3..-1].join('/')) +} + module Oneboxer @@ -26,14 +31,14 @@ module Oneboxer Onebox.preview(url, cache: Rails.cache).to_s end - def self.oneboxer_exists_for_url?(url) + def self.oneboxer_exists_for_url?(url) Onebox.has_matcher?(url) end - def self.invalidate(url) + def self.invalidate(url) Rails.cache.delete(url) end - + # Parse URLs out of HTML, returning the document when finished. def self.each_onebox_link(string_or_doc) doc = string_or_doc diff --git a/spec/components/onebox/engine/discourse_local_onebox_spec.rb b/spec/components/onebox/engine/discourse_local_onebox_spec.rb new file mode 100644 index 00000000000..7c96ccc7343 --- /dev/null +++ b/spec/components/onebox/engine/discourse_local_onebox_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe Onebox::Engine::DiscourseLocalOnebox do + it "matches for a topic url" do + url = "#{Discourse.base_url}/t/hot-topic" + Onebox.has_matcher?(url).should == true + Onebox::Matcher.new(url).oneboxed.should == described_class + end + + it "matches for a post url" do + url = "#{Discourse.base_url}/t/hot-topic/23/2" + Onebox.has_matcher?(url).should == true + Onebox::Matcher.new(url).oneboxed.should == described_class + end + + context "for a link to a post" do + let(:post) { Fabricate(:post) } + let(:post2) { Fabricate(:post, topic: post.topic, post_number: 2) } + + it "returns a link if post isn't found" do + url = "#{Discourse.base_url}/t/not-exist/3/2" + Onebox.preview(url).to_s.should == "#{url}" + end + + it "returns a link if not allowed to see the post" do + url = "#{Discourse.base_url}#{post2.url}" + Guardian.any_instance.stubs(:can_see?).returns(false) + Onebox.preview(url).to_s.should == "#{url}" + end + + it "returns some onebox goodness if post exists and can be seen" do + url = "#{Discourse.base_url}#{post2.url}" + Guardian.any_instance.stubs(:can_see?).returns(true) + html = Onebox.preview(url).to_s + html.should include(post2.user.username) + html.should include(post2.excerpt) + end + end + + context "for a link to a topic" do + let(:post) { Fabricate(:post) } + let(:topic) { post.topic } + + before { topic.last_posted_at = Time.zone.now; topic.save; } # otherwise errors + + it "returns a link if topic isn't found" do + url = "#{Discourse.base_url}/t/not-found/123" + Onebox.preview(url).to_s.should == "#{url}" + end + + it "returns a link if not allowed to see the post" do + url = "#{topic.url}" + Guardian.any_instance.stubs(:can_see?).returns(false) + Onebox.preview(url).to_s.should == "#{url}" + end + + it "returns some onebox goodness if post exists and can be seen" do + url = "#{topic.url}" + Guardian.any_instance.stubs(:can_see?).returns(true) + html = Onebox.preview(url).to_s + html.should include(topic.posts.first.user.username) + html.should include("topic-info") + end + end +end