class RSS2Mail::Feed
Constants
- KEEP
Attributes
content[R]
debug[R]
feed[R]
reload[R]
rss[R]
simple[R]
transport[R]
updated[R]
verbose[R]
Public Class Methods
new(feed, options = {})
click to toggle source
# File lib/rss2mail/feed.rb 35 def initialize(feed, options = {}) 36 raise TypeError, "Hash expected, got #{feed.class}" unless feed.is_a?(Hash) 37 38 required = [:url, :to, :title].delete_if { |key| feed.key?(key) } 39 40 unless required.empty? 41 raise ArgumentError, "Feed incomplete: #{required.join(', ')} missing" 42 end 43 44 @feed = feed 45 @simple = feed[:simple] 46 @updated = feed[:updated] 47 48 @reload = options[:reload] 49 @verbose = options[:verbose] 50 @debug = options[:debug] 51 52 klass, opt = transport_from(options) 53 @transport = "#{klass.name.split('::').last} @ #{opt}" 54 55 extend klass 56 end
Public Instance Methods
deliver(templates)
click to toggle source
# File lib/rss2mail/feed.rb 62 def deliver(templates) 63 check_deliver_requirements if respond_to?(:check_deliver_requirements) 64 65 if (to = Array(feed[:to])).empty? 66 log 'No one to send to' 67 return 68 end 69 70 unless get && parse 71 log 'Nothing to send' 72 return 73 end 74 75 if (items = rss.items).empty? 76 log 'No new items' 77 return 78 end 79 80 type = feed[:content_type] || 'text/html' 81 82 if template = templates[type[/\/(.*)/, 1]] 83 type = "Content-type: #{type}; charset=#{feed[:encoding] || 'UTF-8'}" 84 else 85 log "Template not found: #{type}" 86 return 87 end 88 89 sent = feed[:sent] ||= [] 90 count, title = 0, feed[:title] 91 92 items.each { |item| 93 link, subject, body = render(feed, item, template) 94 95 send_mail(to, "[#{title}] #{subject}", body, type) { 96 sent << link 97 count += 1 98 } if link 99 } 100 101 sent.uniq! 102 sent.slice!(0...-KEEP) 103 104 log "#{count} items sent" 105 count 106 end
Private Instance Methods
error(err = nil, occasion = nil, extra = nil)
click to toggle source
# File lib/rss2mail/feed.rb 239 def error(err = nil, occasion = nil, extra = nil) 240 msg = 'Error' 241 242 msg << " #{occasion}" if occasion 243 msg << ": #{err} (#{err.class})" if err 244 msg << " [#{extra}]" if extra 245 246 msg = [msg, *err.backtrace].join("\n ") if debug 247 248 log msg, true 249 end
get(reload = reload())
click to toggle source
# File lib/rss2mail/feed.rb 133 def get(reload = reload()) 134 conditions = {} 135 136 if reload 137 @content = nil 138 else 139 if etag = feed[:etag] 140 conditions['If-None-Match'] = etag 141 end 142 143 if mtime = feed[:mtime] 144 conditions['If-Modified-Since'] = mtime 145 end 146 end 147 148 log conditions.inspect, debug 149 150 begin 151 open_feed(feed[:url], conditions) { |uri| 152 if etag = uri.meta['etag'] 153 feed[:etag] = etag 154 else 155 feed.delete(:etag) 156 end 157 158 if mtime = begin; uri.last_modified; rescue ArgumentError; end 159 feed[:mtime] = mtime.rfc822 160 else 161 feed.delete(:mtime) 162 end 163 164 unless etag || mtime 165 feed[:updated] = Time.now 166 else 167 feed.delete(:updated) 168 end 169 170 @content ||= uri.read 171 } 172 173 log feed.values_at(:etag, :mtime, :updated).inspect, debug 174 rescue OpenURI::HTTPError => err 175 log "Feed not found or unchanged: #{err} (#{err.class})" 176 rescue Exception => err 177 error err, 'while getting feed' 178 end 179 180 content 181 end
log(msg, verbose = verbose())
click to toggle source
# File lib/rss2mail/feed.rb 235 def log(msg, verbose = verbose()) 236 warn "[#{feed[:title]}] #{msg}" if verbose 237 end
parse(reload = reload())
click to toggle source
# File lib/rss2mail/feed.rb 183 def parse(reload = reload()) 184 @rss = nil if reload 185 186 if content 187 @rss ||= RSS.feed(content, simple) { |err| 188 error err, 'while parsing feed' 189 } 190 191 if rss && !reload 192 if update = updated 193 rss.items.delete_if { |item| (date = item.date) && date <= update } 194 end 195 196 if sent = feed[:sent] 197 set = Set.new(sent) 198 rss.items.delete_if { |item| set.include?(item.link) } 199 end 200 end 201 else 202 log 'Nothing to parse' 203 end 204 205 rss 206 end
render(feed, item, template)
click to toggle source
# File lib/rss2mail/feed.rb 208 def render(feed, item, template) 209 title = item.title 210 link = item.link 211 description = item.description(feed[:unescape_html]) 212 date = item.date 213 author = item.author 214 body = item.body(feed[:body]) 215 subject = item.subject 216 217 log "#{title} / #{date} [#{author}]", debug 218 log "<#{link}>", debug 219 220 [link, subject, ERB.new(template).result(binding)] 221 rescue => err 222 error err, 'while rendering feed', title 223 end
send_mail(*args) { || ... }
click to toggle source
# File lib/rss2mail/feed.rb 225 def send_mail(*args) 226 return if debug 227 228 deliver_mail(*args) 229 230 yield if block_given? 231 rescue Exception => err 232 error err, 'while sending mail', transport 233 end
transport_from(options)
click to toggle source
# File lib/rss2mail/feed.rb 110 def transport_from(options) 111 if lmtp = options[:lmtp] or smtp = options[:smtp] 112 klass = smtp ? Transport::SMTP : Transport::LMTP 113 114 case @smtp = lmtp || smtp 115 when Array # ok 116 when true then @smtp = [] 117 when Fixnum then @smtp = [nil, @smtp] 118 when String then @smtp = @smtp.split(':') 119 else raise TypeError, "Array expected, got #{@smtp.class}" 120 end 121 122 host, port = @smtp.shift, @smtp.shift 123 124 host = klass::DEFAULT_HOST if host.nil? || host.empty? 125 port = klass::DEFAULT_PORT if port.nil? 126 127 [klass, @smtp.unshift(port.to_i).unshift(host)[0, 4].join(':')] 128 else 129 [klass = Transport::Mail, "#{klass::CMD} = #{klass::BIN.inspect}"] 130 end 131 end