Add custom embed_by_username feature

Feature to allow each imported post to be created using a different discourse
username. A possible use case of this is a multi-author blog where discourse
is being used to track comments. This feature allows authors to receive
updates when someone leaves a comment on one of their articles because each of
the imported posts can be created using the discourse username of the author.
This commit is contained in:
Justin Leveck 2014-04-24 09:48:45 -07:00
parent 8e882ad145
commit a78df3d57d
8 changed files with 184 additions and 65 deletions

View file

@ -13,8 +13,7 @@ module Jobs
if args[:user_id]
user = User.find_by(id: args[:user_id])
end
TopicRetriever.new(args[:embed_url], no_throttle: user.try(:staff?)).retrieve
TopicRetriever.new(args[:embed_url], author_username: args[:author_username], no_throttle: user.try(:staff?)).retrieve
end
end

View file

@ -14,8 +14,7 @@ module Jobs
def execute(args)
poll_feed if SiteSetting.feed_polling_enabled? &&
SiteSetting.feed_polling_url.present? &&
SiteSetting.embed_by_username.present?
SiteSetting.feed_polling_url.present?
end
def feed_key
@ -23,22 +22,111 @@ module Jobs
end
def poll_feed
user = User.find_by(username_lower: SiteSetting.embed_by_username.downcase)
return if user.blank?
feed = Feed.new
import_topics(feed.topics)
end
require 'simple-rss'
rss = SimpleRSS.parse open(SiteSetting.feed_polling_url)
private
rss.items.each do |i|
url = i.link
url = i.id if url.blank? || url !~ /^https?\:\/\//
content = i.content || i.description
if content
TopicEmbed.import(user, url, i.title, CGI.unescapeHTML(content.scrub))
end
def import_topics(feed_topics)
feed_topics.each do |topic|
import_topic(topic)
end
end
def import_topic(topic)
if topic.user
TopicEmbed.import(topic.user, topic.url, topic.title, CGI.unescapeHTML(topic.content.scrub))
end
end
class Feed
require 'simple-rss'
SimpleRSS.item_tags << SiteSetting.embed_username_key_from_feed.to_sym
def initialize
@feed_url = SiteSetting.feed_polling_url
end
def topics
feed_topics = []
rss.items.each do |i|
current_feed_topic = FeedTopic.new(i)
feed_topics << current_feed_topic if current_feed_topic.content
end
return feed_topics
end
private
def rss
SimpleRSS.parse open(@feed_url)
end
end
class FeedTopic
def initialize(article_rss_item)
@article_rss_item = article_rss_item
end
def url
link = @article_rss_item.link
if url?(link)
return link
else
return @article_rss_item.id
end
end
def content
@article_rss_item.content || @article_rss_item.description
end
def title
@article_rss_item.title
end
def user
author_user || default_user
end
private
def url?(link)
if link.blank? || link !~ /^https?\:\/\//
return false
else
return true
end
end
def author_username
begin
@article_rss_item.send(SiteSetting.embed_username_key_from_feed.to_sym)
rescue
nil
end
end
def default_user
find_user(SiteSetting.embed_by_username.downcase)
end
def author_user
return nil if !author_username.present?
find_user(author_username)
end
def find_user(user_name)
User.where(username_lower: user_name).first
end
end
end
end

View file

@ -899,6 +899,7 @@ en:
feed_polling_enabled: "Whether to import a RSS/ATOM feed as posts"
feed_polling_url: "URL of RSS/ATOM feed to import"
embed_by_username: "Discourse username of the user who creates the topics"
embed_username_key_from_feed: "Key to pull discourse username from feed"
embed_truncate: "Truncate the imported posts"
embed_category: "Category of created topics"
embed_post_limit: "Maximum number of posts to embed"

View file

@ -469,6 +469,7 @@ embedding:
feed_polling_enabled: false
feed_polling_url: ''
embed_by_username: ''
embed_username_key_from_feed: ''
embed_category: ''
embed_post_limit: 100
embed_truncate: false

View file

@ -2,6 +2,7 @@ class TopicRetriever
def initialize(embed_url, opts=nil)
@embed_url = embed_url
@author_username = opts[:author_username]
@opts = opts || {}
end
@ -46,7 +47,13 @@ class TopicRetriever
end
def fetch_http
user = User.find_by(username_lower: SiteSetting.embed_by_username.downcase)
if @author_username.nil?
username = SiteSetting.embed_by_username.downcase
else
username = @author_username
end
user = User.where(username_lower: username.downcase).first
return if user.blank?
TopicEmbed.import_remote(user, @embed_url)

View file

@ -1,10 +1,24 @@
/* global discourseUrl */
/* global discourseUserName */
/* global discourseEmbedUrl */
(function() {
var comments = document.getElementById('discourse-comments'),
iframe = document.createElement('iframe');
iframe.src = discourseUrl + "embed/comments?embed_url=" + encodeURIComponent(discourseEmbedUrl);
iframe = document.createElement('iframe');
if (typeof discourseUserName === 'undefined') {
iframe.src =
[ discourseUrl,
'embed/comments?embed_url=',
encodeURIComponent(discourseEmbedUrl)
].join('');
} else {
iframe.src =
[ discourseUrl,
'embed/comments?embed_url=',
encodeURIComponent(discourseEmbedUrl),
'&discourse_username=',
discourseUserName
].join('');
}
iframe.id = 'discourse-embed-frame';
iframe.width = "100%";
iframe.frameBorder = "0";

View file

@ -4,43 +4,59 @@ require_dependency 'topic_retriever'
describe TopicRetriever do
let(:embed_url) { "http://eviltrout.com/2013/02/10/why-discourse-uses-emberjs.html" }
let(:topic_retriever) { TopicRetriever.new(embed_url) }
let(:author_username) { "eviltrout" }
let(:topic_retriever) { TopicRetriever.new(embed_url, author_username: author_username) }
it "does not call perform_retrieve when embeddable_host is not set" do
SiteSetting.stubs(:embeddable_host).returns(nil)
topic_retriever.expects(:perform_retrieve).never
topic_retriever.retrieve
end
describe "#retrieve" do
context "when host is invalid" do
before do
topic_retriever.stubs(:invalid_host?).returns(true)
end
it "does not call perform_retrieve when embeddable_host is different than the host of the URL" do
SiteSetting.stubs(:embeddable_host).returns("eviltuna.com")
topic_retriever.expects(:perform_retrieve).never
topic_retriever.retrieve
end
it "does not call perform_retrieve when the embed url is not a url" do
r = TopicRetriever.new("not a url")
r.expects(:perform_retrieve).never
r.retrieve
end
context "with a valid host" do
before do
SiteSetting.stubs(:embeddable_host).returns("eviltrout.com")
it "does not perform_retrieve" do
topic_retriever.expects(:perform_retrieve).never
topic_retriever.retrieve
end
end
it "calls perform_retrieve if it hasn't been retrieved recently" do
topic_retriever.expects(:perform_retrieve).once
topic_retriever.expects(:retrieved_recently?).returns(false)
topic_retriever.retrieve
context "when topics have been retrieived recently" do
before do
topic_retriever.stubs(:retrieved_recently?).returns(true)
end
it "does not perform_retrieve" do
topic_retriever.expects(:perform_retrieve).never
topic_retriever.retrieve
end
end
it "doesn't call perform_retrieve if it's been retrieved recently" do
topic_retriever.expects(:perform_retrieve).never
topic_retriever.expects(:retrieved_recently?).returns(true)
topic_retriever.retrieve
end
context "when host is not invalid" do
before do
topic_retriever.stubs(:invalid_host?).returns(false)
end
context "when topics have been retrieived recently" do
before do
topic_retriever.stubs(:retrieved_recently?).returns(true)
end
it "does not perform_retrieve" do
topic_retriever.expects(:perform_retrieve).never
topic_retriever.retrieve
end
end
context "when topics have not been retrieived recently" do
before do
topic_retriever.stubs(:retrieved_recently?).returns(false)
end
it "does perform_retrieve" do
topic_retriever.expects(:perform_retrieve).once
topic_retriever.retrieve
end
end
end
end
end

View file

@ -2,7 +2,6 @@ require 'spec_helper'
require_dependency 'jobs/regular/process_post'
describe Jobs::PollFeed do
let(:poller) { Jobs::PollFeed.new }
context "execute" do
@ -10,28 +9,22 @@ describe Jobs::PollFeed do
let(:embed_by_username) { "eviltrout" }
it "requires feed_polling_enabled?" do
SiteSetting.stubs(:feed_polling_enabled?).returns(false)
poller.expects(:poll_feed).never
poller.execute({})
SiteSetting.stubs(:feed_polling_enabled?).returns(true)
SiteSetting.stubs(:feed_polling_url).returns(nil)
poller.expects(:poll_feed).never
poller.execute({})
end
it "requires feed_polling_url" do
SiteSetting.stubs(:feed_polling_url).returns(nil)
poller.expects(:poll_feed).never
poller.execute({})
SiteSetting.stubs(:feed_polling_enabled?).returns(false)
SiteSetting.stubs(:feed_polling_url).returns(nil)
poller.expects(:poll_feed).never
poller.execute({})
end
it "requires embed_by_username" do
SiteSetting.stubs(:embed_by_username).returns(nil)
poller.expects(:poll_feed).never
poller.execute({})
end
it "delegates to poll_feed" do
SiteSetting.stubs(:feed_polling_enabled?).returns(true)
SiteSetting.stubs(:feed_polling_url).returns(url)
SiteSetting.stubs(:embed_by_username).returns(embed_by_username)
poller.expects(:poll_feed).once
poller.execute({})
end