* 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
126 lines
3.2 KiB
Ruby
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
|