class News
Constants
- CATEGORIES
- ITEMS_PER_CATEGORY
- STYLE_BANNER
- USER_AGENT
Public Class Methods
Source
# File plugins/news.rb, line 84 def self.clean_google_title(title) title.to_s.sub(/\s+-\s+[^-]+\z/, "").strip end
Source
# File plugins/news.rb, line 79 def self.clean_paragraph(html) text = Nokogiri::HTML.fragment(html.to_s).text text.gsub(/\s+/, " ").strip end
Source
# File plugins/news.rb, line 151 def self.fetch_category_items(category_key, fetch:, limit: ITEMS_PER_CATEGORY) config = CATEGORIES.fetch(category_key) items = config[:feeds].flat_map do |feed| body = fetch.call(feed[:url]) parse_rss_items(body, source: feed[:source]) end unique_items(items, limit: limit) end
Source
# File plugins/news.rb, line 135 def self.format_article(title:, paragraph:, source:) "[#{source}] #{title} #{paragraph}" end
Source
# File plugins/news.rb, line 139 def self.format_section(label, items) lines = [IrcFormat.divider(label)] items.each do |item| lines << format_article( title: item[:title], paragraph: item[:paragraph], source: item[:source] ) end lines.join("\n") end
Source
# File plugins/news.rb, line 161 def self.gather_news(fetch:) sections = CATEGORIES.filter_map do |key, config| items = fetch_category_items(key, fetch: fetch) next if items.empty? format_section(config[:label], items) end return "No news found" if sections.empty? [ news_banner, *sections, IrcFormat.report_footer("ABC ยท SBS ยท Google News") ].join("\n") rescue StandardError "Could not fetch news" end
Source
# File plugins/news.rb, line 96 def self.normalize_item(node, source:) title = rss_element_text(node, "title") paragraph = rss_element_text(node, "description") paragraph = rss_element_text(node, "summary") if paragraph.empty? paragraph = rss_element_text(node, "content") if paragraph.empty? title = clean_google_title(title) if source == "Google News" paragraph = clean_paragraph(paragraph) return nil if title.empty? || paragraph.empty? { title: title, paragraph: paragraph, source: source } end
Source
# File plugins/news.rb, line 88 def self.normalize_title(title) title.to_s.downcase.gsub(/\s+/, " ").strip end
Source
# File plugins/news.rb, line 110 def self.parse_rss_items(xml, source:) doc = REXML::Document.new(xml.to_s) REXML::XPath.match(doc, "//*[local-name()='item' or local-name()='entry']").filter_map do |node| normalize_item(node, source: source) end rescue REXML::ParseException, StandardError [] end
Source
# File plugins/news.rb, line 92 def self.rss_element_text(node, name) REXML::XPath.first(node, ".//*[local-name()='#{name}']")&.text.to_s.strip end
Source
# File plugins/news.rb, line 119 def self.unique_items(items, limit: ITEMS_PER_CATEGORY) seen = {} result = [] items.each do |item| key = normalize_title(item[:title]) next if key.empty? || seen[key] seen[key] = true result << item break if result.length >= limit end result end
Public Instance Methods
Source
# File plugins/news.rb, line 188 def execute(m) themed_flood_safe_reply(m, gather_news) end
Source
# File plugins/news.rb, line 184 def fetch_feed(url) RabbotHttp.fetch(url, user_agent: USER_AGENT) end
Source
# File plugins/news.rb, line 180 def gather_news(fetch: method(:fetch_feed)) self.class.gather_news(fetch: fetch) end