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",
search_type = "application/opensearchdescription%+xml",
search_template_type = "application/atom%+xml",
acquisition_rel = "^http://opds%-spec%.org/acquisition",
image_rel = "http://opds-spec.org/image",
thumbnail_rel = "http://opds-spec.org/image/thumbnail",
@ -59,11 +60,6 @@ function OPDSBrowser:init()
title = "Project Gutenberg",
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",
url = "https://catalog.feedbooks.com/catalog/public_domain.atom",
@ -84,11 +80,6 @@ function OPDSBrowser:init()
title = "Gallica (French)",
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)
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)
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)
local item_table = {}
if not catalog then
@ -408,12 +412,25 @@ function OPDSBrowser:genItemTableFromCatalog(catalog, item_url, username, passwo
if feed.link then
for _, link in ipairs(feed.link) do
if link.type ~= nil then
if link.type:find(self.catalog_type) or
link.type:find(self.search_type) then
if link.type:find(self.catalog_type) then
if link.rel and link.href then
hrefs[link.rel] = build_href(link.href)
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

@ -47,7 +47,7 @@ function OPDSParser:createFlatXTable(xlex, curr_element)
-- if it does, if it's a table, add to it
-- if it doesn't, then add a table
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
curr_element[txt] = {}
end

@ -273,30 +273,37 @@ describe("OPDS module #nocov", function()
describe("OPDS browser module", 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()
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, "Popular")
assert.are.same(item_table[1].url, "http://m.gutenberg.org/ebooks/search.opds/?sort_order=downloads")
assert.are.same(item_table[2].title, "Popular")
assert.are.same(item_table[2].url, "http://m.gutenberg.org/ebooks/search.opds/?sort_order=downloads")
end)
it("should generate URL on rel=popular and rel=new", function()
local catalog = OPDSParser:parse(popular_new_sample)
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://www.feedbooks.com/publicdomain/catalog.atom")
assert.truthy(item_table)
assert.are.same(item_table[1].title, "Most Popular")
assert.are.same(item_table[1].url, "http://www.feedbooks.com/books/top.atom")
assert.are.same(item_table[2].title, "Recently Added")
assert.are.same(item_table[2].url, "http://www.feedbooks.com/books/recent.atom")
assert.are.same(item_table[2].title, "Most Popular")
assert.are.same(item_table[2].url, "http://www.feedbooks.com/books/top.atom")
assert.are.same(item_table[3].title, "Recently Added")
assert.are.same(item_table[3].url, "http://www.feedbooks.com/books/recent.atom")
end)
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 item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds")
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)
@ -305,7 +312,7 @@ describe("OPDS module #nocov", function()
local item_table = OPDSBrowser:genItemTableFromCatalog(catalog, "http://flibusta.net/opds")
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)

Loading…
Cancel
Save