OPDS: Parse Open Search Definition for feeds that support it (#7380)

reviewable/pr7371/r15
Alex Vanderpot 3 years ago committed by GitHub
parent 32b070f3ac
commit ac26ccdc58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -41,6 +41,7 @@ local OPDSBrowser = Menu:extend{
catalog_type = "application/atom%+xml", catalog_type = "application/atom%+xml",
search_type = "application/opensearchdescription%+xml", search_type = "application/opensearchdescription%+xml",
search_template_type = "application/atom%+xml",
acquisition_rel = "^http://opds%-spec%.org/acquisition", acquisition_rel = "^http://opds%-spec%.org/acquisition",
image_rel = "http://opds-spec.org/image", image_rel = "http://opds-spec.org/image",
thumbnail_rel = "http://opds-spec.org/image/thumbnail", thumbnail_rel = "http://opds-spec.org/image/thumbnail",
@ -59,11 +60,6 @@ function OPDSBrowser:init()
title = "Project Gutenberg", title = "Project Gutenberg",
url = "https://m.gutenberg.org/ebooks.opds/?format=opds", url = "https://m.gutenberg.org/ebooks.opds/?format=opds",
}, },
{
title = "Project Gutenberg [Searchable]",
url = "https://m.gutenberg.org/ebooks/search.mobile/?format=opds&query=%s",
searchable = true,
},
{ {
title = "Feedbooks", title = "Feedbooks",
url = "https://catalog.feedbooks.com/catalog/public_domain.atom", url = "https://catalog.feedbooks.com/catalog/public_domain.atom",
@ -84,11 +80,6 @@ function OPDSBrowser:init()
title = "Gallica (French)", title = "Gallica (French)",
url = "https://gallica.bnf.fr/opds", url = "https://gallica.bnf.fr/opds",
}, },
{
title = "Gallica [Fr] [Searchable]",
url = "https://gallica.bnf.fr/services/engine/search/opds?operation=searchRetrieve&query=(gallica all \"%s\")",
searchable = true,
},
} }
G_reader_settings:saveSetting("opds_servers", servers) G_reader_settings:saveSetting("opds_servers", servers)
elseif servers[4] and servers[4].title == "Internet Archive" and servers[4].url == "http://bookserver.archive.org/catalog/" then elseif servers[4] and servers[4].title == "Internet Archive" and servers[4].url == "http://bookserver.archive.org/catalog/" then
@ -392,6 +383,19 @@ function OPDSBrowser:genItemTableFromURL(item_url, username, password)
return self:genItemTableFromCatalog(catalog, item_url, username, password) return self:genItemTableFromCatalog(catalog, item_url, username, password)
end end
function OPDSBrowser:getSearchTemplate(osd_url, username, password)
-- parse search descriptor
local search_descriptor = self:parseFeed(osd_url, username, password)
if search_descriptor and search_descriptor.OpenSearchDescription and search_descriptor.OpenSearchDescription.Url then
for _, candidate in ipairs(search_descriptor.OpenSearchDescription.Url) do
if candidate.type and candidate.template and candidate.type:find(self.search_template_type) then
return candidate.template:gsub('{searchTerms}', '%%s')
end
end
end
end
function OPDSBrowser:genItemTableFromCatalog(catalog, item_url, username, password) function OPDSBrowser:genItemTableFromCatalog(catalog, item_url, username, password)
local item_table = {} local item_table = {}
if not catalog then if not catalog then
@ -408,12 +412,25 @@ function OPDSBrowser:genItemTableFromCatalog(catalog, item_url, username, passwo
if feed.link then if feed.link then
for _, link in ipairs(feed.link) do for _, link in ipairs(feed.link) do
if link.type ~= nil then if link.type ~= nil then
if link.type:find(self.catalog_type) or if link.type:find(self.catalog_type) then
link.type:find(self.search_type) then
if link.rel and link.href then if link.rel and link.href then
hrefs[link.rel] = build_href(link.href) hrefs[link.rel] = build_href(link.href)
end end
end end
if link.type:find(self.search_type) then
if link.href then
local stpl = self:getSearchTemplate(link.href, username, password)
-- insert the search item
local item = {}
item.acquisitions = {}
item.text = "Search"
item.callback = function()
self:browseSearchable(stpl, username, password)
end
table.insert(item_table, item)
end
end
end end
end end
end end

@ -47,7 +47,7 @@ function OPDSParser:createFlatXTable(xlex, curr_element)
-- if it does, if it's a table, add to it -- if it does, if it's a table, add to it
-- if it doesn't, then add a table -- if it doesn't, then add a table
local tab = self:createFlatXTable(xlex) local tab = self:createFlatXTable(xlex)
if txt == "entry" or txt == "link" then if txt == "entry" or txt == "link" or txt == "Url" then
if curr_element[txt] == nil then if curr_element[txt] == nil then
curr_element[txt] = {} curr_element[txt] = {}
end end

@ -273,30 +273,37 @@ describe("OPDS module #nocov", function()
describe("OPDS browser module", function() describe("OPDS browser module", function()
describe("URL generation", function() describe("URL generation", function()
it("should generate search item", function()
local catalog = OPDSParser:parse(navigation_sample)
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://m.gutenberg.org/ebooks.opds/?format=opds")
assert.truthy(item_table)
assert.are.same(item_table[1].title, "Search")
end)
it("should generate URL on rel=subsection", function() it("should generate URL on rel=subsection", function()
local catalog = OPDSParser:parse(navigation_sample) local catalog = OPDSParser:parse(navigation_sample)
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://m.gutenberg.org/ebooks.opds/?format=opds") local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://m.gutenberg.org/ebooks.opds/?format=opds")
assert.truthy(item_table) assert.truthy(item_table)
assert.are.same(item_table[1].title, "Popular") assert.are.same(item_table[2].title, "Popular")
assert.are.same(item_table[1].url, "http://m.gutenberg.org/ebooks/search.opds/?sort_order=downloads") assert.are.same(item_table[2].url, "http://m.gutenberg.org/ebooks/search.opds/?sort_order=downloads")
end) end)
it("should generate URL on rel=popular and rel=new", function() it("should generate URL on rel=popular and rel=new", function()
local catalog = OPDSParser:parse(popular_new_sample) local catalog = OPDSParser:parse(popular_new_sample)
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://www.feedbooks.com/publicdomain/catalog.atom") local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://www.feedbooks.com/publicdomain/catalog.atom")
assert.truthy(item_table) assert.truthy(item_table)
assert.are.same(item_table[1].title, "Most Popular") assert.are.same(item_table[2].title, "Most Popular")
assert.are.same(item_table[1].url, "http://www.feedbooks.com/books/top.atom") assert.are.same(item_table[2].url, "http://www.feedbooks.com/books/top.atom")
assert.are.same(item_table[2].title, "Recently Added") assert.are.same(item_table[3].title, "Recently Added")
assert.are.same(item_table[2].url, "http://www.feedbooks.com/books/recent.atom") assert.are.same(item_table[3].url, "http://www.feedbooks.com/books/recent.atom")
end) end)
it("should use the main URL for faceted links as long as faceted links aren't properly supported", function() it("should use the main URL for faceted links as long as faceted links aren't properly supported", function()
local catalog = OPDSParser:parse(facet_sample) local catalog = OPDSParser:parse(facet_sample)
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds") local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds")
assert.truthy(item_table) assert.truthy(item_table)
assert.are.same(item_table[1].url, "http://flibusta.net/opds/author/75357") assert.are.same(item_table[2].url, "http://flibusta.net/opds/author/75357")
end) end)
end) end)
@ -305,7 +312,7 @@ describe("OPDS module #nocov", function()
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds") local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds")
assert.truthy(item_table) assert.truthy(item_table)
assert.are_not.same(item_table[1].image, "http://flibusta.net/opds/author/75357") assert.are_not.same(item_table[2].image, "http://flibusta.net/opds/author/75357")
end) end)
end) end)
end) end)

Loading…
Cancel
Save