rss_feed 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: caed8664b546d8b48b6c0b83154e6961a6fd3414
4
+ data.tar.gz: 9a8d22d3e9c4d4b95459a18d98ab986ed5824951
5
+ SHA512:
6
+ metadata.gz: 7daa4da3a909178b686f973ee0fe999b0c45c6c820b162e94cda7b7f9ee2157379c6a96a26fca815bdbd74bc023469760b362872bcffc6a85bdaa09a8c4f75cf
7
+ data.tar.gz: 90baf4ce6576a6a64e96dab6ea7f42966d6b3f27e3a985330f4194f99f76939d1b9f3f38e02c6e2f3f75cf3759c3d18bfba6939b4b0cb4badf8dfba837fb26b0
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 0.1.0, released 2011-06-16
2
+
3
+ * Initial release on GitHub
4
+
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2011 Oliver Eilhard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # RssFeed
2
+
3
+ Convenient classes for parsing an [RSS feed](http://www.rssboard.org/rss-specification)
4
+
5
+ ## Links
6
+
7
+ * [RSS 2.0 Specification](http://www.rssboard.org/rss-specification)
8
+ * [RSS 1.0 Specification](http://web.resource.org/rss/1.0/)
9
+ * [RSS on Wikipedia](http://en.wikipedia.org/wiki/RSS)
10
+
@@ -0,0 +1,2 @@
1
+ class String
2
+ end
@@ -0,0 +1,9 @@
1
+ class Object
2
+ alias_method :try, :__send__
3
+ end
4
+
5
+ class NilClass
6
+ def try(*args)
7
+ nil
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ require 'rss_feed/core_ext/try.rb'
2
+ require 'rss_feed/core_ext/string_ext.rb'
@@ -0,0 +1,38 @@
1
+ require 'rss_feed/open_search_query'
2
+
3
+ module RSSFeed
4
+ class OpenSearch
5
+ # Initializes the Open Search extensions.
6
+ def initialize(node)
7
+ @node = node
8
+ end
9
+
10
+ def present?
11
+ !self.total_results.nil?
12
+ end
13
+
14
+ def total_results
15
+ @node.at_xpath("rss/channel/opensearch:totalResults", ::RSSFeed::NS).content.to_i rescue nil
16
+ end
17
+
18
+ def start_index
19
+ @node.at_xpath("rss/channel/opensearch:startIndex", ::RSSFeed::NS).content.to_i rescue nil
20
+ end
21
+
22
+ def items_per_page
23
+ @node.at_xpath("rss/channel/opensearch:itemsPerPage", ::RSSFeed::NS).content.to_i rescue nil
24
+ end
25
+
26
+ # queries
27
+ def queries
28
+ nodes = @node.xpath("rss/channel/opensearch:Query", ::RSSFeed::NS) rescue nil
29
+ nodes.map { |node| OpenSearchQuery.new(node) } if nodes
30
+ end
31
+
32
+ # first
33
+ # previous
34
+ # next
35
+ # last
36
+ # search
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module RSSFeed
2
+ class OpenSearchQuery
3
+ # Initializes the Open Search Query element.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ def role
9
+ @node["role"]
10
+ end
11
+
12
+ def search_terms
13
+ @node["searchTerms"]
14
+ end
15
+
16
+ def start_page
17
+ @node["startPage"].to_i
18
+ end
19
+
20
+ def start_index
21
+ @node["startIndex"].to_i
22
+ end
23
+
24
+ def items_per_page
25
+ @node["itemsPerPage"].to_i
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module RSSFeed
2
+ class RSSCategory
3
+ # Initializes the link.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # Identifies the domain (optional).
9
+ def domain
10
+ @node["domain"]
11
+ end
12
+
13
+ # Content of the RSS category.
14
+ def content
15
+ @node.content
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,177 @@
1
+ # encoding: utf-8
2
+
3
+ require 'nokogiri'
4
+ require 'rss_feed/core_ext'
5
+ require 'rss_feed/rss_category'
6
+ require 'rss_feed/rss_channel_item'
7
+ require 'rss_feed/rss_cloud'
8
+ require 'rss_feed/rss_guid'
9
+ require 'rss_feed/rss_image'
10
+ require 'rss_feed/rss_text_input'
11
+ require 'rss_feed/open_search'
12
+
13
+ module RSSFeed
14
+ # RSSFeed::RSSChannel is the central place for
15
+ # working with feeds in the RSS format.
16
+ #
17
+ # Opening an RSS feed from the network or a file system
18
+ # is done like this:
19
+ #
20
+ # feed = RSSFeed::RSSChannel.open(open("http://example.com/rss.xml"))
21
+ #
22
+ # If you have a file you should do:
23
+ #
24
+ # f = File.open("rss.xml")
25
+ # feed = RSSFeed::RSSChannel.open(f)
26
+ # f.close
27
+ #
28
+ # If you have an XML string you can do:
29
+ #
30
+ # feed = RSSFeed::RSSChannel.open("<rss version='1.0'> ...")
31
+ #
32
+ # One can open and parse the feed like so:
33
+ #
34
+ # RSSFeed::RSSChannel.open(...) do |feed|
35
+ # puts feed.title
36
+ # feed.items do |item|
37
+ # puts item.title
38
+ # end
39
+ # end
40
+ #
41
+ # You can access OpenSearch extensions by using +RSSChannel.open_search+.
42
+ # Access to other embedded XML types are available by using RSSChannel.doc+
43
+ # directly. It's a +Nokogiri::XML+ instance.
44
+ #
45
+ # RSSFeed uses Nokogiri for parsing.
46
+ #
47
+ class RSSChannel
48
+
49
+ attr_reader :doc
50
+
51
+ def initialize(doc)
52
+ @doc = doc
53
+ end
54
+
55
+ def self.open(string_or_io, url = nil, encoding = nil)
56
+ doc = Nokogiri::XML(string_or_io, url, encoding)
57
+ channel = RSSChannel.new(doc)
58
+ yield channel if block_given?
59
+ channel
60
+ end
61
+
62
+ # Title (required).
63
+ def title
64
+ @doc.at_xpath("rss/channel/title").content
65
+ end
66
+
67
+ # Link (required).
68
+ def link
69
+ @doc.at_xpath("rss/channel/link").content
70
+ end
71
+
72
+ # Description (required).
73
+ def description
74
+ @doc.at_xpath("rss/channel/description").content
75
+ end
76
+
77
+ # Language (optional).
78
+ def language
79
+ @doc.at_xpath("rss/channel/language").try(:content)
80
+ end
81
+
82
+ # Copyright (optional).
83
+ def copyright
84
+ @doc.at_xpath("rss/channel/copyright").try(:content)
85
+ end
86
+
87
+ # Managing editor (optional).
88
+ def managing_editor
89
+ @doc.at_xpath("rss/channel/managingEditor").try(:content)
90
+ end
91
+
92
+ # Publication date (optional).
93
+ def pub_date
94
+ if date = @doc.at_xpath("rss/channel/pubDate").try(:content)
95
+ Time.rfc822(date)
96
+ end
97
+ end
98
+
99
+ # Last build date (optional).
100
+ def last_build_date
101
+ if date = @doc.at_xpath("rss/channel/lastBuildDate").try(:content)
102
+ Time.rfc822(date)
103
+ end
104
+ end
105
+
106
+ # Category (optional).
107
+ def category
108
+ if node = @doc.at_xpath("rss/channel/category")
109
+ RSSCategory.new(node)
110
+ end
111
+ end
112
+
113
+ # Generator (optional).
114
+ def generator
115
+ @doc.at_xpath("rss/channel/generator").try(:content)
116
+ end
117
+
118
+ # Documentation link (optional).
119
+ def docs
120
+ @doc.at_xpath("rss/channel/docs").try(:content)
121
+ end
122
+
123
+ # Cloud (optional)
124
+ def cloud
125
+ if node = @doc.at_xpath("rss/channel/cloud")
126
+ RSSCloud.new(node)
127
+ end
128
+ end
129
+
130
+ # Time to live in minutes (optional).
131
+ def ttl
132
+ @doc.at_xpath("rss/channel/ttl").try(:content).nonzero?
133
+ end
134
+
135
+ # Image (optional).
136
+ def image
137
+ if node = @doc.at_xpath("rss/channel/image")
138
+ RSSImage.new(node)
139
+ end
140
+ end
141
+
142
+ # PICS rating (optional).
143
+ def rating
144
+ @doc.at_xpath("rss/channel/rating").try(:content)
145
+ end
146
+
147
+ # Text input box (optional).
148
+ def text_input
149
+ if node = @doc.at_xpath("rss/channel/textInput")
150
+ RSSTextInput.new(node)
151
+ end
152
+ end
153
+
154
+ # Hint for aggregators telling them which hours they can skip (optional).
155
+ def skip_hours
156
+ @doc.at_xpath("rss/channel/skipHours").try(:content).nonzero?
157
+ end
158
+
159
+ # Hint for aggregators telling them which days they can skip (optional).
160
+ def skip_days
161
+ @doc.at_xpath("rss/channel/skipDays").try(:content).nonzero?
162
+ end
163
+
164
+ # Array of channel items (optional).
165
+ def items
166
+ nodes = @doc.xpath("rss/channel/item") || []
167
+ nodes.map { |node| RSSChannelItem.new(node) }
168
+ end
169
+
170
+ # Open Search extensions (optional)
171
+ def open_search
172
+ @open_search ||= OpenSearch.new(@doc)
173
+ end
174
+
175
+ end
176
+ end
177
+
@@ -0,0 +1,73 @@
1
+ module RSSFeed
2
+ class RSSChannelItem
3
+
4
+ attr_reader :node
5
+
6
+ def initialize(node)
7
+ @node = node
8
+ end
9
+
10
+ # Title (required).
11
+ def title
12
+ @node.at_xpath("title").content
13
+ end
14
+
15
+ # Link (required).
16
+ def link
17
+ @node.at_xpath("link").content
18
+ end
19
+
20
+ # Description (required).
21
+ def description
22
+ @node.at_xpath("description").content
23
+ end
24
+
25
+ # Email address of the author (optional).
26
+ def author
27
+ @node.at_xpath("author").try(:content)
28
+ end
29
+
30
+ # Array of categories (optional).
31
+ def categories
32
+ if nodes = @node.xpath("category")
33
+ nodes.map { |node| RSSCategory.new(node) }
34
+ end
35
+ end
36
+
37
+ # Array of URLs to comments (optional).
38
+ def comments
39
+ if nodes = @node.xpath("comments")
40
+ nodes.map { |node| node.content }.compact
41
+ end
42
+ end
43
+
44
+ # Enclosure (optional).
45
+ def enclosure
46
+ if node = @node.at_xpath("enclosure")
47
+ RSSEnclosure.new(node)
48
+ end
49
+ end
50
+
51
+ # GUID (optional).
52
+ def guid
53
+ if node = @node.at_xpath("guid")
54
+ RSSGuid.new(node)
55
+ end
56
+ end
57
+
58
+ # Publication date (optional).
59
+ def pub_date
60
+ if date = @node.at_xpath("pubDate").try(:content)
61
+ Time.rfc822(date)
62
+ end
63
+ end
64
+
65
+ # Source (optional).
66
+ def source
67
+ if node = @node.at_xpath("source")
68
+ RSSSource.new(node)
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,35 @@
1
+ module RSSFeed
2
+ class RSSCloud
3
+
4
+ # Initializes the cloud element.
5
+ def initialize(node)
6
+ @node = node
7
+ end
8
+
9
+ # Domain
10
+ def domain
11
+ @node["domain"]
12
+ end
13
+
14
+ # Port
15
+ def port
16
+ @node["port"].nonzero?
17
+ end
18
+
19
+ # Path
20
+ def path
21
+ @node["path"]
22
+ end
23
+
24
+ # Register procedure
25
+ def register_procedure
26
+ @node["registerProcedure"]
27
+ end
28
+
29
+ # Protocol
30
+ def protocol
31
+ @node["protocol"]
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module RSSFeed
2
+ class RSSEnclosure
3
+ # Initializes the enclosure element.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # URL (required)
9
+ def url
10
+ @node["url"]
11
+ end
12
+
13
+ # Length (required)
14
+ def length
15
+ @node["length"]
16
+ end
17
+
18
+ # Media type (required)
19
+ def type
20
+ @node["type"]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ module RSSFeed
2
+ class RSSGuid
3
+ # Initializes the link.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # Content
9
+ def content
10
+ @node.content
11
+ end
12
+
13
+ # Is permalink?
14
+ def is_permalink?
15
+ @node["isPermaLink"]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ module RSSFeed
2
+ class RSSImage
3
+ # Initializes the image element.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # URL (required)
9
+ def url
10
+ @node.at_xpath("url").content
11
+ end
12
+
13
+ # Title (required)
14
+ def title
15
+ @node.at_xpath("title").content
16
+ end
17
+
18
+ # Link (required)
19
+ def link
20
+ @node.at_xpath("link").content
21
+ end
22
+
23
+ # Width (optional)
24
+ def width
25
+ @node.at_xpath("width").try(:content).to_i
26
+ end
27
+
28
+ # Height (optional)
29
+ def height
30
+ @node.at_xpath("height").try(:content).to_i
31
+ end
32
+
33
+ # Description (optional)
34
+ def description
35
+ @node.at_xpath("description").try(:content)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module RSSFeed
2
+ class RSSSource
3
+ # Initializes the source element.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # URL (required)
9
+ def url
10
+ @node["url"]
11
+ end
12
+
13
+ # Content
14
+ def content
15
+ @node.content
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ module RSSFeed
2
+ class RSSTextInput
3
+ # Initializes the text input element.
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ # Title (required)
9
+ def title
10
+ @node.at_xpath("title").content
11
+ end
12
+
13
+ # Description (required)
14
+ def description
15
+ @node.at_xpath("description").content
16
+ end
17
+
18
+ # Name (required)
19
+ def name
20
+ @node.at_xpath("name").content
21
+ end
22
+
23
+ # Link (required)
24
+ def link
25
+ @node.at_xpath("link").content
26
+ end
27
+ end
28
+ end
data/lib/rss_feed.rb ADDED
@@ -0,0 +1,30 @@
1
+ # Copyright (C) 2011 Oliver Eilhard
2
+ #
3
+ # This library is freely distributable under
4
+ # the terms of an MIT-style license.
5
+ # See COPYING or http://www.opensource.org/licenses/mit-license.php.
6
+
7
+ # This library is for parsing RSS feeds.
8
+
9
+ module RSSFeed
10
+ VERSION = "0.1.1"
11
+
12
+ # OpenSearch 1.1 Draft 4 namespace
13
+ NS_OPENSEARCH_11 = "http://a9.com/-/spec/opensearch/1.1/"
14
+
15
+ # Well-known namespaces for use in Nokogiri
16
+ NS = {"rss" => "", "opensearch" => NS_OPENSEARCH_11}
17
+
18
+ autoload :CoreExt, 'rss_feed/core_ext.rb'
19
+ autoload :OpenSearch, 'rss_feed/open_search.rb'
20
+ autoload :OpenSearchQuery, 'rss_feed/open_search_query.rb'
21
+ autoload :RSSChannel, 'rss_feed/rss_channel.rb'
22
+ autoload :RSSChannelItem, 'rss_feed/rss_channel_item.rb'
23
+ autoload :RSSCategory, 'rss_feed/rss_category.rb'
24
+ autoload :RSSCloud, 'rss_feed/rss_cloud.rb'
25
+ autoload :RSSEnclosure, 'rss_feed/rss_enclosure.rb'
26
+ autoload :RSSGuid, 'rss_feed/rss_guid.rb'
27
+ autoload :RSSImage, 'rss_feed/rss_image.rb'
28
+ autoload :RSSSource, 'rss_feed/rss_source.rb'
29
+ autoload :RSSTextInput, 'rss_feed/rss_text_input.rb'
30
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rss_feed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Oliver Eilhard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 3.12.1
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.12'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.12.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '12.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '12.3'
61
+ - !ruby/object:Gem::Dependency
62
+ name: nokogiri
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.8'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 1.8.2
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '1.8'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 1.8.2
81
+ description: Ruby library for parsing RSS feeds.
82
+ email:
83
+ - oliver.eilhard@gmail.com
84
+ executables: []
85
+ extensions: []
86
+ extra_rdoc_files:
87
+ - CHANGELOG.md
88
+ - LICENSE
89
+ - README.md
90
+ files:
91
+ - CHANGELOG.md
92
+ - LICENSE
93
+ - README.md
94
+ - lib/rss_feed.rb
95
+ - lib/rss_feed/core_ext.rb
96
+ - lib/rss_feed/core_ext/string_ext.rb
97
+ - lib/rss_feed/core_ext/try.rb
98
+ - lib/rss_feed/open_search.rb
99
+ - lib/rss_feed/open_search_query.rb
100
+ - lib/rss_feed/rss_category.rb
101
+ - lib/rss_feed/rss_channel.rb
102
+ - lib/rss_feed/rss_channel_item.rb
103
+ - lib/rss_feed/rss_cloud.rb
104
+ - lib/rss_feed/rss_enclosure.rb
105
+ - lib/rss_feed/rss_guid.rb
106
+ - lib/rss_feed/rss_image.rb
107
+ - lib/rss_feed/rss_source.rb
108
+ - lib/rss_feed/rss_text_input.rb
109
+ homepage: http://github.com/olivere/rss_feed
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options:
115
+ - "--charset=UTF-8"
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: 1.3.6
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.5.2
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Ruby library for parsing RSS feeds.
134
+ test_files: []