docbrown/app/services/rss_reader.rb
Andy Zhao 47d9ec27fb Allow users to belong to multiple orgs (#2583)
* Allow user to have many orgs

* Allow users to handle multi orgs in settings

* Make rounded buttons inline

* Add multi org function to dashboards

* Fix merge conflicts

* Fix mistake in merge conflict fix oops

* Display the correct membership level

* Fix accessibility issues

* Display organizations for article editors

* Handle submitting org id with preact editors

* Make listings work with multiple organizations

* Allow listings to have multiple orgs on create

* Display the correct number of credits for each org

* Move script tag to Webpack

* Allow multi orgs for purchasing and viewing credits

* Use OrganizationMembership as authorization check

* Display multiple organizations for notifications

* Allow dashboard to be viewable under multi-orgs

* Remove unused method

* Add multi-org functionality for article editors

* Show pro dashboard buttons for member+ org levels

* Leave the correct organization

* Allow article API to change org id

* Add left-out authorization method oops

* Make nav buttons a bit more clear

* Fix merge conflict

* Fix adding org id for /api/articles and tests

* Fix tests for org policy

* Use proper logic for displaying org members

* Update org actions with new authorization

* Use correct org when creating a listing

* Remove additional payment charge oops

* Mark org notifications as read with authorization

* Remove deprecated post_as_organization attribute

* Use new org_admin syntax

* Remove deprecated org logic for article create and update

* Default all RSS posts to not belong to any org

* Render org_member page for guest users

* Update org policy spec to work with multi orgs

* Use org_membership for org traits and move identity code

* Use org_member trait

* Update to work with multi-orgs

* Validate article's org_id if param org_id is blank

* Make  a let variable

* Remove unnecessary eager load for credits

* Fix HTML structure and org logic for non-org users

* Update credits spec for multi-org

* Add test for failed payment when purchased by org

* Lint listings_spec

* Test that the listing was created under the user

* Add tests for POST /listings multi-org

* Use double quotes for classes

* Fix /manage and a few other multi-org bugs

* Fix test for multi org

* Use correct method SQL exists? not Rails exist?

* Fix reads spec for multi-org

* Fix org_controller actions to work with multi org

* Test only multi org and not old usage and fix leave_org

* Fix org showing user profile img test for multi-org

* Fix org logic for users with no orgs

* Remove switch org functionality

* Update tests and add hidden param for org id

* Redirect to the specific organization

* Test other org button actions

* Use settings_notice instead of legacy notice and refactor

* Fix weird extra end issue prob from merge conflicts

* Test for with new flash key

* Fix user_views_org tests for multi-org

* Test for new flash message

* Update snapshot with new a11y html

* Move styling to stylesheet

* Add site admins functionality

* Move org_member? method in user model and refactor

* Use unspent_credits_count for organizations

* Add tests for /listings/new and minor bug fixes

* Use .present? in case of empty array

* Fix a lingering deprecated method

* Use greater than 1 for random numbers

* Add tests for counting spent and unspent credits
2019-06-04 09:30:52 -04:00

126 lines
3.2 KiB
Ruby

class RssReader
def self.get_all_articles(force = true)
new.get_all_articles(force)
end
def get_all_articles(force = true)
User.where.not(feed_url: [nil, ""]).find_each do |user|
# unless forced, fetch sparingly
next if force == false && (rand(2) == 1 || user.feed_fetched_at > 15.minutes.ago)
create_articles_for_user(user)
end
end
def fetch_user(user)
create_articles_for_user(user)
end
def valid_feed_url?(link)
true if fetch_rss(link)
rescue StandardError
false
end
private
def create_articles_for_user(user)
user.update_column(:feed_fetched_at, Time.current)
feed = fetch_rss(user.feed_url.strip)
feed.entries.reverse_each do |item|
make_from_rss_item(item, user, feed)
rescue StandardError => e
log_error(
"RssReaderError: occurred while creating article",
rss_reader_info: {
user: user.username,
feed_url: user.feed_url,
item_count: get_item_count_error(feed),
error: e
},
)
end
rescue StandardError => e
log_error(
"RssReaderError: occurred while fetching feed",
rss_reader_info: {
user: user.username,
feed_url: user.feed_url,
item_count: get_item_count_error(feed),
error: e
},
)
end
def get_item_count_error(feed)
if feed
feed.entries ? feed.entries.length : "no count"
else
"NIL FEED, INVALID URL"
end
end
def fetch_rss(url)
xml = HTTParty.get(url).body
Feedjira::Feed.parse xml
end
def make_from_rss_item(item, user, feed)
return if medium_reply?(item) || article_exists?(user, item)
feed_source_url = item.url.strip.split("?source=")[0]
article = Article.create!(
feed_source_url: feed_source_url,
user_id: user.id,
published_at: item.published,
published_from_feed: true,
show_comments: true,
body_markdown: RssReader::Assembler.call(item, user, feed, feed_source_url),
organization_id: nil,
)
send_slack_notification(article)
end
def get_host_without_www(url)
url = "http://#{url}" if URI.parse(url).scheme.nil?
host = URI.parse(url).host.downcase
host.start_with?("www.") ? host[4..-1] : host
end
def medium_reply?(item)
get_host_without_www(item.url.strip) == "medium.com" &&
!item[:categories] &&
content_is_not_the_title?(item)
end
def content_is_not_the_title?(item)
# [[:space:]] removes all whitespace, including unicode ones.
content = item.content.gsub(/[[:space:]]/, " ")
title = item.title.delete("")
content.include?(title)
end
def article_exists?(user, item)
title = item.title.strip.gsub('"', '\"')
feed_source_url = item.url.strip.split("?source=")[0]
relation = user.articles
relation.where(title: title).or(relation.where(feed_source_url: feed_source_url)).exists?
end
def send_slack_notification(article)
return unless Rails.env.production?
SlackBot.delay.ping(
"New Article Retrieved via RSS: #{article.title}\nhttps://dev.to#{article.path}",
channel: "activity",
username: "article_bot",
icon_emoji: ":robot_face:",
)
end
def log_error(error_msg, metadata)
Rails.logger.error(error_msg, metadata)
end
end