Class: OPDS::Feed Abstract

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/opds/feed.rb

Overview

This class is abstract.

Not really abstract as it’s full fledged, but it should not be used directly

Feed class is used as an ancestor to NavigationFeed and AcquisitionFeed it handles all the parsing

Direct Known Subclasses

AcquisitionFeed, NavigationFeed

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

#log, log

Constructor Details

#initialize(browser = nil) ⇒ Feed

Returns a new instance of Feed.



17
18
19
20
# File 'lib/opds/feed.rb', line 17

def initialize(browser=nil)
	@browser=browser
	@browser||=OPDS::Support::Browser.new
end

Instance Attribute Details

#entriesArray<Entry> (readonly)

Entry list

Returns:

  • (Array<Entry>)

    list of parsed entries

See Also:



14
15
16
# File 'lib/opds/feed.rb', line 14

def entries
  @entries
end

#raw_docNokogiri::XML::Document (readonly)

“Raw” Nokogiri document used while parsing. It might useful to access atom foreign markup

Returns:

  • (Nokogiri::XML::Document)

    Parsed document



10
11
12
# File 'lib/opds/feed.rb', line 10

def raw_doc
  @raw_doc
end

Class Method Details

.from_nokogiri(content, browser = nil) ⇒ Feed

Create a feed from a nokogiri document

Parameters:

  • content (Nokogiri::XML::Document)

    nokogiri document

  • browser (OPDS::Support::Browser) (defaults to: nil)

    an optional compatible browser to use

Returns:

  • (Feed)

    new feed



88
89
90
91
92
93
# File 'lib/opds/feed.rb', line 88

def self.from_nokogiri(content,browser=nil)
	z=self.new browser
	z.instance_variable_set('@raw_doc',content)
	z.serialize!
	z
end

.parse_raw(txt, opts = {}, browser = nil) ⇒ AcquisitionFeed, NavigationFeed

Will parse a text stream as an OPDS Catalog, internaly used by #parse_url

Parameters:

  • txt (String)

    text to parse

  • opts (Hash) (defaults to: {})

    options to pass to the parser

  • browser (OPDS::Support::Browser) (defaults to: nil)

    an optional compatible browser to use

Returns:



75
76
77
78
79
80
81
# File 'lib/opds/feed.rb', line 75

def self.parse_raw(txt,opts={},browser=nil)
	parser=OPDSParser.new(opts)
	pfeed=parser.parse(txt,browser)
	type=parser.sniffed_type
	return pfeed unless type.nil?
	nil
end

.parse_url(url, browser = OPDS::Support::Browser.new, parser_opts = {}) ⇒ AcquisitionFeed, ...

Parse the given url.

If the resource at the give url is not an OPDS Catalog, this method will try to find a linked catalog. If many are available it will take the first one with a priority given to nil rel or rel=“related” catalogs.

Parameters:

  • url (String)

    url to parse

  • parser_opts (defaults to: {})

    parser options (unused at the moment)

  • browser (OPDS::Support::Browser) (defaults to: OPDS::Support::Browser.new)

    an optional compatible browser to use

Returns:

See Also:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/opds/feed.rb', line 46

def self.parse_url(url,browser=OPDS::Support::Browser.new,parser_opts={})
	@browser=browser
	@browser.go_to(url)
	if @browser.ok?
		parsed = self.parse_raw(@browser.body,parser_opts,browser) 
		if parsed.nil?
			disco=@browser.discover(@browser.current_location)
			if disco.size > 0
				d=disco[nil]
				d||=disco['related']
				d||=disco
				Logging.log("Discovered : #{d.first.url}")
				return d.first.navigate
			end
			return false
		else
			return  parsed
		end
	else
		return false
	end
end

Instance Method Details

#authorHash

Returns Feed author (keys : name,uri,email).

Returns:

  • (Hash)

    Feed author (keys : name,uri,email)



154
155
156
157
158
159
160
# File 'lib/opds/feed.rb', line 154

def author
	{
		:name => text(raw_doc.at('/xmlns:feed/xmlns:author/xmlns:name',raw_doc.root.namespaces)),
		:uri => text(raw_doc.at('/xmlns:feed/xmlns:author/xmlns:uri',raw_doc.root.namespaces)),
		:email => text(raw_doc.at('/xmlns:feed/xmlns:author/xmlns:email',raw_doc.root.namespaces))
	}
end

#first_page?Boolean

Is it the first page ?

Returns:

  • (Boolean)

    Boolean



180
181
182
# File 'lib/opds/feed.rb', line 180

def first_page?
	!prev_page_url if paginated?
end

#iconString

Returns Feed icon definition.

Returns:

  • (String)

    Feed icon definition



111
112
113
# File 'lib/opds/feed.rb', line 111

def icon
	text(raw_doc.at('/xmlns:feed/xmlns:icon',raw_doc.root.namespaces))
end

#idString

Returns Feed id.

Returns:

  • (String)

    Feed id



149
150
151
# File 'lib/opds/feed.rb', line 149

def id
	text(raw_doc.at('/xmlns:feed/xmlns:id',raw_doc.root.namespaces))
end

#inspectObject



202
203
204
# File 'lib/opds/feed.rb', line 202

def inspect
	"#<#{self.class}:0x#{self.object_id.abs.to_s(16)} entries(count):#{@entries.size} #{instance_variables.reject{|e| e=='@raw_doc'||e=='@entries' }.collect{|e| "#{e}=#{instance_variable_get(e).inspect}"}.join(' ')} >"
end

#last_page?Boolean

Is it the last page ?

Returns:

  • (Boolean)

    Boolean



186
187
188
# File 'lib/opds/feed.rb', line 186

def last_page?
	!next_page_url if paginated?
end

Returns Set with atom feed level links.

Returns:



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/opds/feed.rb', line 116

def links
	if !@links || @links.size ==0
		@links=OPDS::Support::LinkSet.new @browser
		raw_doc.xpath('/xmlns:feed/xmlns:link',raw_doc.root.namespaces).each do |n|
			text=nil
			text=n.attributes['title'].value unless n.attributes['title'].nil?
			type=n.attributes['type'].value unless n.attributes['type'].nil?
			link=n.attributes['href'].value
			unless n.attributes['rel'].nil?
				n.attributes['rel'].value.split.each do |rel|
					if rel=='http://opds-spec.org/facet'
						group=n.attribute_with_ns('facetGroup','http://opds-spec.org/2010/catalog')
						group=group.value unless group.nil?
						active=n.attribute_with_ns('activeFacet','http://opds-spec.org/2010/catalog')
						active=active.value unless active.nil?
						count=n.attribute_with_ns('count','http://purl.org/syndication/thread/1.0')
						count=count.value unless count.nil?

					@links.push_facet(link,text,type,group,active,count)
					else
					@links.push(rel,link,text,type)
					end
				end
			else
				@links.push(nil,link,text,type)
			end
		end

	end
	@links
end

#next_pageAcquisitionFeed, ...

Get next page feed

Returns:



192
193
194
# File 'lib/opds/feed.rb', line 192

def next_page
	Feed.parse_url(next_page_url,@browser)
end

#next_page_urlString

Returns Next page url.

Returns:

  • (String)

    Next page url



163
164
165
# File 'lib/opds/feed.rb', line 163

def next_page_url
	links.link_url(:rel => 'next')
end

#paginated?Boolean

Is the feed paginated ?

Returns:

  • (Boolean)

    Boolean



174
175
176
# File 'lib/opds/feed.rb', line 174

def paginated?
	!next_page_url.nil?||!prev_page_url.nil?
end

#prev_pageAcquisitionFeed, ...

Get previous page feed

Returns:



198
199
200
# File 'lib/opds/feed.rb', line 198

def prev_page
	Feed.parse_url(prev_page_url,@browser)
end

#prev_page_urlString

Returns Previous page url.

Returns:

  • (String)

    Previous page url



168
169
170
# File 'lib/opds/feed.rb', line 168

def prev_page_url
	links.link_url(:rel => 'prev')
end

#serialize!Object

TODO:

really make private

read xml entries into the entry list struct



98
99
100
101
102
# File 'lib/opds/feed.rb', line 98

def serialize!
	@entries=raw_doc.xpath('/xmlns:feed/xmlns:entry',raw_doc.root.namespaces).map do |el|
		OPDS::Entry.from_nokogiri(el,raw_doc.root.namespaces,@browser)
	end
end

#titleString

Returns Feed title.

Returns:

  • (String)

    Feed title



106
107
108
# File 'lib/opds/feed.rb', line 106

def title
	text(raw_doc.at('/xmlns:feed/xmlns:title',raw_doc.root.namespaces))
end