concerto_simple_rss 0.7 → 0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7621d623a546cb35b8ac6671dbdba81f570ebfb
4
- data.tar.gz: 6a1ac67eb1add40753f8eb0d73f5c43e9d7badbc
3
+ metadata.gz: aa7e279123911a7477853d01e1ac97f6a9a9d6b9
4
+ data.tar.gz: 9f34f22652616db1752b96f52431aef37809d6c0
5
5
  SHA512:
6
- metadata.gz: 8d139ccbfe054efd6cc6ad626958354bd2de718e1651cc091f8ef24e30cb4a45257520e94ba8c8c02633b42978fcae2bb4e9f3bd3e1e9158ba86fa0d3f701a58
7
- data.tar.gz: 475cba55dc73ca805b7511242bc08d8b9dc5d7e009f7d233eb31a9e91e4db18a0426343e468497f89438fdbebcd1a982febe6450e8bea2496e0100b6b3ceaef6
6
+ metadata.gz: d3052c45ead7cabeb914416882979d34fcec3f207ad5d906acc6aaecf08d28101c7d4a92b43dbd67346032dac7b083c8ad50d3867ee9c6dc10fa8ae687804254
7
+ data.tar.gz: 6a341b98a8a0471de16426be656a717b9d0306f080710581adc41c8720080c8acecbc44c25eb23e4189814e619cb0ccf3fbb1f2e4ba0e22f4db023e8809f3409
@@ -12,6 +12,8 @@ function previewSimpleRss() {
12
12
  var url = $('input#simple_rss_config_url').data('url');
13
13
  if (url) {
14
14
  rss_url = $('input#simple_rss_config_url').val();
15
+ userid = $('input#simple_rss_config_url_userid').val();
16
+ password = $('input#simple_rss_config_url_password').val();
15
17
  output_format = $('select#simple_rss_config_output_format').val();
16
18
  max_items = $('input#simple_rss_config_max_items').val();
17
19
  reverse_order = $('select#simple_rss_config_reverse_order').val();
@@ -22,6 +24,8 @@ function previewSimpleRss() {
22
24
  }
23
25
  $("#preview_div").load(url, { data: {
24
26
  url: rss_url,
27
+ url_userid: userid,
28
+ url_password: password,
25
29
  output_format: output_format,
26
30
  max_items: max_items,
27
31
  reverse_order: reverse_order,
@@ -40,6 +44,8 @@ function initializeSimpleRssHandlers() {
40
44
  // on blur and change of url, display format, reverse_order, max items, and xsl
41
45
  // not on keyup (poor man's debouncing technique?)
42
46
  $('input#simple_rss_config_url').on('blur', previewSimpleRss);
47
+ $('input#simple_rss_config_url_userid').on('blur', previewSimpleRss);
48
+ $('input#simple_rss_config_url_password').on('blur', previewSimpleRss);
43
49
  $('select#simple_rss_config_output_format').on('change', previewSimpleRss);
44
50
  $('input#simple_rss_config_max_items').on('blur', previewSimpleRss);
45
51
  $('select#simple_rss_config_reverse_order').on('change', previewSimpleRss);
@@ -1,137 +1,176 @@
1
1
  class SimpleRss < DynamicContent
2
+ require 'base64'
2
3
 
3
4
  DISPLAY_NAME = 'RSS Feed'
4
5
 
5
6
  validate :validate_config, :validate_feed
6
7
 
8
+ # Load a configuration hash.
9
+ # Converts the JSON data stored for the content into the configuration.
10
+ # Called during `after_find`.
11
+ def load_config
12
+ j = JSON.load(self.data)
13
+
14
+ # decrypt fields
15
+ unless j.blank?
16
+ encrypted_userid = Base64.decode64(j['url_userid_enc']) unless j['url_userid_enc'].blank?
17
+ encrypted_password = Base64.decode64(j['url_password_enc']) unless j['url_password_enc'].blank?
18
+
19
+ j['url_userid'] = (encrypted_userid.blank? ? "" : encrypted_userid.decrypt)
20
+ j['url_password'] = (encrypted_password.blank? ? "" : encrypted_password.decrypt)
21
+ end
22
+
23
+ self.config = j
24
+ end
25
+
26
+ # Prepare the configuration to be saved.
27
+ # Compress the config hash back into JSON to be stored in the database.
28
+ # Called during `before_validation`.
29
+ def save_config
30
+ j = self.config.deep_dup
31
+
32
+ # encrypt fields
33
+ j['url_userid_enc'] = (j['url_userid'].blank? ? "" : Base64.encode64(j['url_userid'].encrypt))
34
+ j['url_password_enc'] = (j['url_password'].blank? ? "" : Base64.encode64(j['url_password'].encrypt))
35
+ j.delete 'url_userid'
36
+ j.delete 'url_password'
37
+ self.data = JSON.dump(j)
38
+ end
39
+
7
40
  def build_content
8
41
  contents = []
9
42
 
10
43
  url = self.config['url']
11
- type, feed_title, rss, raw = fetch_feed(url)
12
-
13
- if (["RSS", "ATOM"].include? type) && !feed_title.blank?
14
- # it is a valid feed
15
- if !self.config['reverse_order'].blank? && self.config['reverse_order'] == '1'
16
- rss.items.reverse!
17
- end
18
- feed_items = rss.items
19
- if !self.config['max_items'].blank? && self.config['max_items'].to_i > 0
20
- feed_items = feed_items.first(self.config['max_items'].to_i)
21
- end
22
- case self.config['output_format']
23
- when 'headlines'
24
- feed_items.each_slice(5).with_index do |items, index|
25
- htmltext = HtmlText.new()
26
- htmltext.name = "#{feed_title} (#{index+1})"
27
- htmltext.data = sanitize("<h1>#{feed_title}</h1> #{items_to_html(items, type)}")
28
- contents << htmltext
44
+ unless url.blank?
45
+ url_userid = self.config['url_userid']
46
+ url_password = self.config['url_password']
47
+ type, feed_title, rss, raw = fetch_feed(url, url_userid, url_password)
48
+
49
+ if (["RSS", "ATOM"].include? type) && !feed_title.blank?
50
+ # it is a valid feed
51
+ if !self.config['reverse_order'].blank? && self.config['reverse_order'] == '1'
52
+ rss.items.reverse!
29
53
  end
30
- when 'detailed'
31
- feed_items.each_with_index do |item, index|
32
- htmltext = HtmlText.new()
33
- htmltext.name = "#{feed_title} (#{index+1})"
34
- htmltext.data = sanitize(item_to_html(item, type))
35
- contents << htmltext
36
- end
37
- when 'xslt'
38
- require 'rexml/document'
39
- require 'xml/xslt'
40
-
41
- #XML::XSLT.registerErrorHandler { |string| puts string }
42
- xslt = XML::XSLT.new()
43
- begin
44
- xslt.xml = REXML::Document.new(raw)
45
- rescue REXML::ParseException => e
46
- Rails.logger.error("Unable to parse incoming feed: #{e.message}")
47
- raise "Unable to parse incoming feed. "
48
- rescue => e
49
- raise e
54
+ feed_items = rss.items
55
+ if !self.config['max_items'].blank? && self.config['max_items'].to_i > 0
56
+ feed_items = feed_items.first(self.config['max_items'].to_i)
50
57
  end
58
+ case self.config['output_format']
59
+ when 'headlines'
60
+ feed_items.each_slice(5).with_index do |items, index|
61
+ htmltext = HtmlText.new()
62
+ htmltext.name = "#{feed_title} (#{index+1})"
63
+ htmltext.data = sanitize("<h1>#{feed_title}</h1> #{items_to_html(items, type)}")
64
+ contents << htmltext
65
+ end
66
+ when 'detailed'
67
+ feed_items.each_with_index do |item, index|
68
+ htmltext = HtmlText.new()
69
+ htmltext.name = "#{feed_title} (#{index+1})"
70
+ htmltext.data = sanitize(item_to_html(item, type))
71
+ contents << htmltext
72
+ end
73
+ when 'xslt'
74
+ require 'rexml/document'
75
+ require 'xml/xslt'
51
76
 
52
- begin
53
- xslt.xsl = REXML::Document.new(self.config['xsl'])
54
- rescue REXML::ParseException => e
55
- Rails.logger.error("Unable to parse Xsl: #{e.message}")
56
- # fmt is <rexml::parseexception: message :> trace ... so just pull out the message
57
- s = e.message
58
- msg_stop = s.index(">")
59
- s = s.slice(23, msg_stop - 23) if !msg_stop.nil?
60
- raise "Unable to parse Xsl. #{s}"
61
- rescue => e
62
- raise e
63
- end
77
+ #XML::XSLT.registerErrorHandler { |string| puts string }
78
+ xslt = XML::XSLT.new()
79
+ begin
80
+ xslt.xml = REXML::Document.new(raw)
81
+ rescue REXML::ParseException => e
82
+ Rails.logger.error("Unable to parse incoming feed: #{e.message}")
83
+ raise "Unable to parse incoming feed. "
84
+ rescue => e
85
+ raise e
86
+ end
64
87
 
65
- # add a replace [gsub] function for more powerful transforms. You can use this in a transform
66
- # by adding the bogus namespace http://concerto.functions
67
- # A nodeset comes in as an array of REXML::Elements
68
- XML::XSLT.registerExtFunc("http://concerto.functions", "replace") do |nodes, pattern, replacement|
69
- result = xslt_replace(nodes, pattern, replacement)
70
- result
71
- end
88
+ begin
89
+ xslt.xsl = REXML::Document.new(self.config['xsl'])
90
+ rescue REXML::ParseException => e
91
+ Rails.logger.error("Unable to parse Xsl: #{e.message}")
92
+ # fmt is <rexml::parseexception: message :> trace ... so just pull out the message
93
+ s = e.message
94
+ msg_stop = s.index(">")
95
+ s = s.slice(23, msg_stop - 23) if !msg_stop.nil?
96
+ raise "Unable to parse Xsl. #{s}"
97
+ rescue => e
98
+ raise e
99
+ end
72
100
 
73
- XML::XSLT.registerExtFunc("http://schemas.concerto-signage.org/functions", "replace") do |nodes, pattern, replacement|
74
- result = xslt_replace(nodes, pattern, replacement)
75
- result
76
- end
101
+ # add a replace [gsub] function for more powerful transforms. You can use this in a transform
102
+ # by adding the bogus namespace http://concerto.functions
103
+ # A nodeset comes in as an array of REXML::Elements
104
+ XML::XSLT.registerExtFunc("http://concerto.functions", "replace") do |nodes, pattern, replacement|
105
+ result = xslt_replace(nodes, pattern, replacement)
106
+ result
107
+ end
77
108
 
78
- data = xslt.serve()
79
- # xslt.serve does always return a string with ASCII-8BIT encoding regardless of what the actual encoding is
80
- data = data.force_encoding(xslt.xml.encoding) if data
81
-
82
- # try to load the transformed data as an xml document so we can see if there are
83
- # mulitple content-items that we need to parse out, if we cant then treat it as one content item
84
- begin
85
- data_xml = REXML::Document.new('<root>' + data + '</root>')
86
- nodes = REXML::XPath.match(data_xml, "//content-item")
87
- # if there are no content-items then add the whole result (data) as one content
88
- if nodes.count == 0
89
- htmltext = HtmlText.new()
90
- htmltext.name = "#{feed_title}"
91
- htmltext.data = sanitize(data)
92
- contents << htmltext
93
- else
94
- # if there are any content-items then add each one as a separate content
95
- # and strip off the content-item wrapper
96
- nodes.each do |n|
109
+ XML::XSLT.registerExtFunc("http://schemas.concerto-signage.org/functions", "replace") do |nodes, pattern, replacement|
110
+ result = xslt_replace(nodes, pattern, replacement)
111
+ result
112
+ end
113
+
114
+ data = xslt.serve()
115
+ # xslt.serve does always return a string with ASCII-8BIT encoding regardless of what the actual encoding is
116
+ data = data.force_encoding(xslt.xml.encoding) if data
117
+
118
+ # try to load the transformed data as an xml document so we can see if there are
119
+ # mulitple content-items that we need to parse out, if we cant then treat it as one content item
120
+ begin
121
+ data_xml = REXML::Document.new('<root>' + data + '</root>')
122
+ nodes = REXML::XPath.match(data_xml, "//content-item")
123
+ # if there are no content-items then add the whole result (data) as one content
124
+ if nodes.count == 0
97
125
  htmltext = HtmlText.new()
98
126
  htmltext.name = "#{feed_title}"
99
- htmltext.data = sanitize(n.to_s.gsub(/^\s*\<content-item\>/, '').gsub(/\<\/content-item\>\s*$/,''))
127
+ htmltext.data = sanitize(data)
100
128
  contents << htmltext
129
+ else
130
+ # if there are any content-items then add each one as a separate content
131
+ # and strip off the content-item wrapper
132
+ nodes.each do |n|
133
+ htmltext = HtmlText.new()
134
+ htmltext.name = "#{feed_title}"
135
+ htmltext.data = sanitize(n.to_s.gsub(/^\s*\<content-item\>/, '').gsub(/\<\/content-item\>\s*$/,''))
136
+ contents << htmltext
137
+ end
101
138
  end
102
- end
103
- rescue => e
104
- # maybe the html was not xml compliant-- this happens frequently in rss feed descriptions
105
- # look for another separator and use it, if it exists
106
-
107
- if data.include?("</content-item>")
108
- # if there are any content-items then add each one as a separate content
109
- # and strip off the content-item wrapper
110
- data.split("</content-item>").each do |n|
139
+ rescue => e
140
+ # maybe the html was not xml compliant-- this happens frequently in rss feed descriptions
141
+ # look for another separator and use it, if it exists
142
+
143
+ if data.include?("</content-item>")
144
+ # if there are any content-items then add each one as a separate content
145
+ # and strip off the content-item wrapper
146
+ data.split("</content-item>").each do |n|
147
+ htmltext = HtmlText.new()
148
+ htmltext.name = "#{feed_title}"
149
+ htmltext.data = sanitize(n.sub("<content-item>", ""))
150
+ contents << htmltext if !htmltext.data.strip.blank?
151
+ end
152
+
153
+ else
154
+ Rails.logger.error("unable to parse resultant xml, assuming it is one content item #{e.message}")
155
+ # raise "unable to parse resultant xml #{e.message}"
156
+ # add the whole result as one content
111
157
  htmltext = HtmlText.new()
112
158
  htmltext.name = "#{feed_title}"
113
- htmltext.data = sanitize(n.sub("<content-item>", ""))
114
- contents << htmltext if !htmltext.data.strip.blank?
159
+ htmltext.data = sanitize(data)
160
+ contents << htmltext
115
161
  end
116
-
117
- else
118
- Rails.logger.error("unable to parse resultant xml, assuming it is one content item #{e.message}")
119
- # raise "unable to parse resultant xml #{e.message}"
120
- # add the whole result as one content
121
- htmltext = HtmlText.new()
122
- htmltext.name = "#{feed_title}"
123
- htmltext.data = sanitize(data)
124
- contents << htmltext
125
162
  end
163
+ else
164
+ raise ArgumentError, 'Unexpected output format for RSS feed.'
126
165
  end
166
+ elsif type == "ERROR"
167
+ raise rss
127
168
  else
128
- raise ArgumentError, 'Unexpected output format for RSS feed.'
169
+ Rails.logger.error("could not fetch #{type} feed for #{feed_title} at #{url}")
170
+ raise "Unexpected feed format for #{url}."
129
171
  end
130
- else
131
- Rails.logger.error("could not fetch #{type} feed for #{feed_title} at #{url}")
132
- raise "Unexpected feed format for #{url}."
133
172
  end
134
-
173
+
135
174
  return contents
136
175
  end
137
176
 
@@ -162,7 +201,8 @@ class SimpleRss < DynamicContent
162
201
  end
163
202
 
164
203
  # fetch the feed, return the type, title, and contents (parsed) and raw feed (unparsed)
165
- def fetch_feed(url)
204
+ def fetch_feed(url, url_userid, url_password)
205
+ require 'encryptor'
166
206
  require 'rss'
167
207
  require 'open-uri'
168
208
 
@@ -171,28 +211,35 @@ class SimpleRss < DynamicContent
171
211
  rss = nil
172
212
  feed = nil
173
213
 
174
- begin
175
- # cache same url for 1 minute to alleviate redundant calls when previewing
176
- feed = Rails.cache.fetch(url, :expires_in => 1.minute) do
177
- open(url).read()
178
- end
179
-
180
- rss = RSS::Parser.parse(feed, false, true)
181
- raise "feed could not be parsed" if rss.nil?
182
- rescue => e
183
- # cant parse rss or url is bad
184
- Rails.logger.debug("unable to fetch or parse feed - #{url}, #{e.message}")
185
- rss = e.message
186
- else
187
- type = rss.feed_type.upcase
214
+ unless url.blank?
215
+ begin
216
+ # cache same url for 1 minute to alleviate redundant calls when previewing
217
+ feed = Rails.cache.fetch(url, :expires_in => 1.minute) do
218
+ if url_userid.blank? or url_password.blank?
219
+ open(url).read()
220
+ else
221
+ open(url, http_basic_authentication: [url_userid, url_password]).read()
222
+ end
223
+ end
188
224
 
189
- case type
190
- when "RSS"
191
- title = rss.channel.title
192
- when "ATOM"
193
- title = rss.title.content
225
+ rss = RSS::Parser.parse(feed, false, true)
226
+ raise "feed could not be parsed" if rss.nil?
227
+ rescue => e
228
+ # cant parse rss or url is bad
229
+ Rails.logger.debug("unable to fetch or parse feed - #{url}, #{e.message}")
230
+ rss = e.message
231
+ type = "ERROR"
194
232
  else
195
- #title = "unknown feed type"
233
+ type = rss.feed_type.upcase
234
+
235
+ case type
236
+ when "RSS"
237
+ title = rss.channel.title
238
+ when "ATOM"
239
+ title = rss.title.content
240
+ else
241
+ #title = "unknown feed type"
242
+ end
196
243
  end
197
244
  end
198
245
 
@@ -238,16 +285,18 @@ class SimpleRss < DynamicContent
238
285
  # Simple RSS processing needs a feed URL and the format of the output content.
239
286
  def self.form_attributes
240
287
  attributes = super()
241
- attributes.concat([:config => [:url, :output_format, :reverse_order, :max_items, :xsl, :sanitize_tags]])
288
+ attributes.concat([:config => [:url, :url_userid, :url_password, :output_format, :reverse_order, :max_items, :xsl, :sanitize_tags]])
242
289
  end
243
290
 
244
291
  # if the feed is valid we store the title in config
245
292
  def validate_feed
246
293
  url = self.config['url']
294
+ url_userid = self.config['url_userid']
295
+ url_password = self.config['url_password']
247
296
  unless url.blank?
248
- Rails.logger.debug("looking up feed title for #{url}")
297
+ Rails.logger.debug("looking up feed title for #{url}")
249
298
 
250
- type, title = fetch_feed(url)
299
+ type, title = fetch_feed(url, url_userid, url_password)
251
300
  if (["RSS", "ATOM"].include? type) && !title.blank?
252
301
  self.config['title'] = title
253
302
  else
@@ -270,11 +319,13 @@ class SimpleRss < DynamicContent
270
319
  errors.add(:base, "XSL Markup can't be blank when using the XSLT Display Format")
271
320
  else
272
321
  url = self.config['url']
322
+ url_userid = self.config['url_userid']
323
+ url_password = self.config['url_password']
273
324
  unless url.blank?
274
325
  require 'rexml/document'
275
326
  require 'xml/xslt'
276
327
 
277
- type, title, rss, raw = fetch_feed(url)
328
+ type, title, rss, raw = fetch_feed(url, url_userid, url_password)
278
329
  if ["RSS", "ATOM"].include? type
279
330
  begin
280
331
  xslt = XML::XSLT.new()
@@ -295,6 +346,8 @@ class SimpleRss < DynamicContent
295
346
  begin
296
347
  o = SimpleRss.create()
297
348
  o.config['url'] = data[:url]
349
+ o.config['url_userid'] = data[:url_userid]
350
+ o.config['url_password'] = data[:url_password]
298
351
  o.config['output_format'] = data[:output_format]
299
352
  o.config['max_items'] = data[:max_items]
300
353
  o.config['reverse_order'] = data[:reverse_order]
@@ -6,9 +6,26 @@
6
6
  <%= config.label :url %>
7
7
  <div class="input">
8
8
  <%= config.url_field :url, :placeholder => 'http://feeds.bbci.co.uk/news/rss.xml', :class => "input-xxlarge", :value => @content.config['url'], "data-url" => preview_contents_path %>
9
- <div><small>You can verify an RSS feed at <a href="http://validator.w3.org/feed/" target="_blank">http://validator.w3.org/feed/</a></small></div>
10
9
  </div>
11
10
  </div>
11
+
12
+ <div class="row-fluid">
13
+ <div class="span6">
14
+ <div class="clearfix span6">
15
+ <%= label_tooltip "simple_rss", :url_userid, t("activerecord.attributes.simple_rss.config_url_userid"), tip: t("basic_auth_tip") %>
16
+ <div class="input">
17
+ <%= config.text_field :url_userid, :class => "input-medium", autocomplete: :off %>
18
+ </div>
19
+ </div>
20
+ <div class="clearfix span6">
21
+ <%= config.label :url_password, t("activerecord.attributes.simple_rss.config_url_password") %>
22
+ <div class="input">
23
+ <%= config.password_field :url_password, :class => "input-medium", autocomplete: :off %>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
28
+
12
29
  <div class="clearfix">
13
30
  <%= config.label :output_format, 'Display Format' %>
14
31
  <div class="input">
@@ -0,0 +1,7 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ simple_rss:
5
+ config_url_userid: "Basic Auth Id"
6
+ config_url_password: "Password"
7
+ basic_auth_tip: "Leave the User Id and Password blank if the URL does not require Basic HTTP Authentication."
@@ -1,9 +1,13 @@
1
1
  module ConcertoSimpleRss
2
2
  class Engine < ::Rails::Engine
3
+ require 'encryptor'
4
+
3
5
  isolate_namespace ConcertoSimpleRss
4
6
 
5
7
  initializer "register content type" do |app|
6
8
  app.config.content_types << SimpleRss
9
+
10
+ Encryptor.default_options.merge!(key: ENV["SECRET_KEY_BASE"])
7
11
  end
8
12
  end
9
13
  end
@@ -1,3 +1,3 @@
1
1
  module ConcertoSimpleRss
2
- VERSION = "0.7"
2
+ VERSION = "0.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concerto_simple_rss
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '0.8'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Michalski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-10 00:00:00.000000000 Z
11
+ date: 2015-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: encryptor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: ruby-xslt
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +71,7 @@ files:
57
71
  - app/views/contents/simple_rss/_render_grid.html.erb
58
72
  - app/views/contents/simple_rss/_render_tile.html.erb
59
73
  - app/views/contents/simple_rss/_tab_icon.html.erb
74
+ - config/locales/en.yml
60
75
  - config/routes.rb
61
76
  - lib/concerto_simple_rss.rb
62
77
  - lib/concerto_simple_rss/engine.rb
@@ -113,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
128
  version: '0'
114
129
  requirements: []
115
130
  rubyforge_project:
116
- rubygems_version: 2.4.5
131
+ rubygems_version: 2.2.3
117
132
  signing_key:
118
133
  specification_version: 4
119
134
  summary: RSS Dynamic Concerto for Concerto 2.