From edd7eecafcd1081c6beb67624636a125478cef2c Mon Sep 17 00:00:00 2001 From: Ryan Kulp Date: Mon, 8 Jun 2026 07:47:18 -0400 Subject: [PATCH] Update rss_feed plugin from core repo --- README.md | 1 + lib/rss_feed/rss_feed.rb | 100 ++++++++++++++++++ lib/rss_feed/views/full.html.erb | 7 ++ lib/rss_feed/views/half_horizontal.html.erb | 7 ++ lib/rss_feed/views/half_vertical.html.erb | 7 ++ lib/rss_feed/views/quadrant.html.erb | 7 ++ lib/rss_feed/views/shared/_feed.html.erb | 24 +++++ lib/rss_feed/views/shared/_title_bar.html.erb | 5 + 8 files changed, 158 insertions(+) create mode 100644 lib/rss_feed/rss_feed.rb create mode 100644 lib/rss_feed/views/full.html.erb create mode 100644 lib/rss_feed/views/half_horizontal.html.erb create mode 100644 lib/rss_feed/views/half_vertical.html.erb create mode 100644 lib/rss_feed/views/quadrant.html.erb create mode 100644 lib/rss_feed/views/shared/_feed.html.erb create mode 100644 lib/rss_feed/views/shared/_title_bar.html.erb diff --git a/README.md b/README.md index 5729f6c..e122627 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ community Recipes: - [Nano Banana Dashboard](/lib/nano_banana_dashboard) - [Notion](/lib/notion) - [Parcel](/lib/parcel) +- [Rss Feed](/lib/rss_feed) - [Shopify](/lib/shopify) - [Stock Price](/lib/stock_price) - [Tempest Weather Station](/lib/tempest_weather_station) diff --git a/lib/rss_feed/rss_feed.rb b/lib/rss_feed/rss_feed.rb new file mode 100644 index 0000000..5fbce6c --- /dev/null +++ b/lib/rss_feed/rss_feed.rb @@ -0,0 +1,100 @@ +module Plugins + class RssFeed < Base + + def locals + { rss_feed: } + end + + private + + def rss_feed + feed = process_feed + feed.is_a?(Array) ? feed : [feed] + end + + def process_feed + validate_uri(settings['url']) + response = fetch(settings['url'].strip, headers:) + + raise InvalidURL unless response.respond_to?(:code) && response.respond_to?(:body) + raise InvalidURL if response.code.to_i >= 400 + return content_error(StandardError.new("Response Code: #{response.code}")) if response.code != 200 + return content_error(StandardError.new("No Content")) if response.body.nil? || response.body.empty? + + feed = RSS::Parser.parse(response.body, validate: false) + + if layout == 'featured' + normalize_feed(feed&.items&.first) + elsif layout == 'list' + feed&.items&.[](0..7)&.map do |post| + normalize_feed(post, strip_to_text: true) + end + end + rescue OpenURI::HTTPError, RSS::NotWellFormedError, RSS::TooMuchTagError => e + content_error(e) + rescue InvalidURL, URI::InvalidURIError, OpenSSL::SSL::SSLError => e + handle_erroring_state(e) + content_error(e) + end + + def normalize_feed(post, strip_to_text: false) + content = if post.is_a?(RSS::Atom::Feed::Entry) + { + title: post&.title&.content, + content: post&.summary&.content || post&.content&.to_s + }.compact + else + { + title: post&.title, + content: post&.content_encoded || post&.description + }.compact + end + return content_error(StandardError.new("No Content")) if content.empty? + + if strip_to_text + strip_html(content) + else + dither_image(content) + end + end + + def validate_uri(url) + raise InvalidURL unless url =~ URI::DEFAULT_PARSER.make_regexp + end + + # added 2025-01-08 per customer observation that some rss feeds prevent fetches without user-agent present + def headers + { + 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9' + } + end + + def dither_image(feed) + content = feed[:content] + return feed if content.nil? + + content.gsub!(%r{}, '') + feed[:content] = content + feed + end + + # Make content in the list view plaintext so we don't overflow. + def strip_html(feed) + content = feed[:content] + return feed if content.nil? + + plain_text = ActionController::Base.helpers.strip_tags(content) + feed[:content] = plain_text.squish.truncate(200) + feed + end + + def content_error(error) + { + title: 'Error while parsing RSS content', + content: "Message: #{error&.message}" + } + end + + def layout = settings['layout'] || 'featured' + end +end diff --git a/lib/rss_feed/views/full.html.erb b/lib/rss_feed/views/full.html.erb new file mode 100644 index 0000000..bb2601a --- /dev/null +++ b/lib/rss_feed/views/full.html.erb @@ -0,0 +1,7 @@ +
+
+ <%= render "plugins/rss_feed/shared/feed", rss_feed: rss_feed %> +
+ + <%= render "plugins/rss_feed/shared/title_bar", instance_name: instance_name %> +
diff --git a/lib/rss_feed/views/half_horizontal.html.erb b/lib/rss_feed/views/half_horizontal.html.erb new file mode 100644 index 0000000..e458bfb --- /dev/null +++ b/lib/rss_feed/views/half_horizontal.html.erb @@ -0,0 +1,7 @@ +
+
+ <%= render "plugins/rss_feed/shared/feed", rss_feed: rss_feed %> +
+ + <%= render "plugins/rss_feed/shared/title_bar", instance_name: instance_name %> +
diff --git a/lib/rss_feed/views/half_vertical.html.erb b/lib/rss_feed/views/half_vertical.html.erb new file mode 100644 index 0000000..e87e38b --- /dev/null +++ b/lib/rss_feed/views/half_vertical.html.erb @@ -0,0 +1,7 @@ +
+
+ <%= render "plugins/rss_feed/shared/feed", rss_feed: rss_feed %> +
+ + <%= render "plugins/rss_feed/shared/title_bar", instance_name: instance_name %> +
diff --git a/lib/rss_feed/views/quadrant.html.erb b/lib/rss_feed/views/quadrant.html.erb new file mode 100644 index 0000000..3cd5c14 --- /dev/null +++ b/lib/rss_feed/views/quadrant.html.erb @@ -0,0 +1,7 @@ +
+
+ <%= render "plugins/rss_feed/shared/feed", rss_feed: rss_feed %> +
+ + <%= render "plugins/rss_feed/shared/title_bar", instance_name: instance_name %> +
diff --git a/lib/rss_feed/views/shared/_feed.html.erb b/lib/rss_feed/views/shared/_feed.html.erb new file mode 100644 index 0000000..479bd1e --- /dev/null +++ b/lib/rss_feed/views/shared/_feed.html.erb @@ -0,0 +1,24 @@ +
+
+ <% if rss_feed.count == 1 %> +
+ + <%= rss_feed.first[:title] %> +
<%= sanitize(rss_feed.first[:content]) %>
+
+ <% else %> + <% rss_feed.each_with_index do |feed, idx| %> +
+
+ <%= idx + 1 %> +
+
+ <%= simple_format(render_markdown(feed[:title])) %> +

<%= sanitize(feed[:content]) %>

+
+
+ <% end %> + <% end %> +
+
+ diff --git a/lib/rss_feed/views/shared/_title_bar.html.erb b/lib/rss_feed/views/shared/_title_bar.html.erb new file mode 100644 index 0000000..9461c51 --- /dev/null +++ b/lib/rss_feed/views/shared/_title_bar.html.erb @@ -0,0 +1,5 @@ +
+ <%= image_tag plugin_image_path("rss--render.svg"), class: "image", alt: "" %> + RSS Feed + <%= instance_name %> +