/
item.rb
90 lines (71 loc) 路 2.48 KB
/
item.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
require 'faraday'
require 'faraday_middleware'
require 'open-uri'
require 'nokogiri'
require_relative 'item_extractors'
require_relative 'attribute_post_processors'
module Html2rss
class Item
def initialize(xml, config)
@xml = xml
@config = config
end
private_class_method :new
def respond_to_missing?(method_name, _include_private = false)
config.attribute?(method_name) || super
end
def method_missing(method_name, *_args)
return super unless respond_to_missing?(method_name)
attribute_options = config.attribute_options(method_name)
extractor = ItemExtractors.get_extractor(attribute_options['extractor'])
value = extractor.new(xml, attribute_options).get
post_process(value, attribute_options.fetch('post_process', false))
end
def available_attributes
@available_attributes ||= (%w[title link description author comments updated] &
@config.attribute_names) - ['categories']
end
##
# At least a title or a description is required to be a valid RSS 2.0 item.
def valid?
title = self.title if config.attribute?(:title)
description = self.description if config.attribute?(:description)
[title, description].join != ''
end
##
# @return [Array]
def categories
categories = config.categories
categories.map!(&method(:method_missing))
categories.uniq!
categories.keep_if { |category| category.to_s != '' }
end
##
# @return [Array]
def self.from_url(url, config)
body = get_body_from_url(url, config)
Nokogiri::HTML(body).css(config.selector('items')).map do |xml_item|
new xml_item, config
end
end
private
def self.get_body_from_url(url, config)
body = Faraday.new(url: url, headers: config.headers) do |faraday|
faraday.use FaradayMiddleware::FollowRedirects
faraday.adapter Faraday.default_adapter
end.get.body
config.json? ? Html2rss::Utils.hash_to_xml(JSON.parse(body)) : body
end
private_class_method :get_body_from_url
attr_reader :xml, :config
def post_process(value, post_process_options)
return value unless post_process_options
[post_process_options].flatten.each do |options|
value = AttributePostProcessors.get_processor(options['name'])
.new(value, options: options, item: self, config: @config)
.get
end
value
end
end
end