Skip to content

Commit

Permalink
Merge pull request #459 from kiwix/opds_category_support
Browse files Browse the repository at this point in the history
Support for book categories in OPDS feed
  • Loading branch information
kelson42 authored Mar 17, 2021
2 parents 0f36879 + b7b0bdb commit f7c867f
Show file tree
Hide file tree
Showing 14 changed files with 512 additions and 16 deletions.
5 changes: 5 additions & 0 deletions include/book.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Book
const std::string& getDate() const { return m_date; }
const std::string& getUrl() const { return m_url; }
const std::string& getName() const { return m_name; }
std::string getCategory() const;
const std::string& getTags() const { return m_tags; }
std::string getTagStr(const std::string& tagName) const;
bool getTagBool(const std::string& tagName) const;
Expand Down Expand Up @@ -94,13 +95,17 @@ class Book
void setFaviconMimeType(const std::string& faviconMimeType) { m_faviconMimeType = faviconMimeType; }
void setDownloadId(const std::string& downloadId) { m_downloadId = downloadId; }

private:
std::string getCategoryFromTags() const;

protected:
std::string m_id;
std::string m_downloadId;
std::string m_path;
bool m_pathValid = false;
std::string m_title;
std::string m_description;
std::string m_category;
std::string m_language;
std::string m_creator;
std::string m_publisher;
Expand Down
2 changes: 2 additions & 0 deletions include/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Filter {
uint64_t activeFilters;
std::vector<std::string> _acceptTags;
std::vector<std::string> _rejectTags;
std::string _category;
std::string _lang;
std::string _publisher;
std::string _creator;
Expand Down Expand Up @@ -96,6 +97,7 @@ class Filter {
Filter& acceptTags(std::vector<std::string> tags);
Filter& rejectTags(std::vector<std::string> tags);

Filter& category(std::string category);
Filter& lang(std::string lang);
Filter& publisher(std::string publisher);
Filter& creator(std::string creator);
Expand Down
23 changes: 23 additions & 0 deletions src/book.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ bool Book::update(const kiwix::Book& other)
m_name = other.m_name;
m_flavour = other.m_flavour;
m_tags = other.m_tags;
m_category = other.m_category;
m_origId = other.m_origId;
m_articleCount = other.m_articleCount;
m_mediaCount = other.m_mediaCount;
Expand Down Expand Up @@ -88,6 +89,7 @@ void Book::update(const kiwix::Reader& reader)
m_name = reader.getName();
m_flavour = reader.getFlavour();
m_tags = reader.getTags();
m_category = getCategoryFromTags();
m_origId = reader.getOrigId();
m_articleCount = reader.getArticleCount();
m_mediaCount = reader.getMediaCount();
Expand Down Expand Up @@ -127,6 +129,8 @@ void Book::updateFromXml(const pugi::xml_node& node, const std::string& baseDir)
try {
m_downloadId = ATTR("downloadId");
} catch(...) {}
const auto catattr = node.attribute("category");
m_category = catattr.empty() ? getCategoryFromTags() : catattr.value();
}
#undef ATTR

Expand Down Expand Up @@ -156,6 +160,8 @@ void Book::updateFromOpds(const pugi::xml_node& node, const std::string& urlHost
m_name = VALUE("name");
m_flavour = VALUE("flavour");
m_tags = VALUE("tags");
const auto catnode = node.child("category");
m_category = catnode.empty() ? getCategoryFromTags() : catnode.child_value();
m_articleCount = strtoull(VALUE("articleCount"), 0, 0);
m_mediaCount = strtoull(VALUE("mediaCount"), 0, 0);
for(auto linkNode = node.child("link"); linkNode;
Expand Down Expand Up @@ -220,4 +226,21 @@ bool Book::getTagBool(const std::string& tagName) const {
return convertStrToBool(getTagStr(tagName));
}

std::string Book::getCategory() const
{
return m_category;
}

std::string Book::getCategoryFromTags() const
{
try
{
return getTagStr("category");
}
catch ( const std::out_of_range& )
{
return "";
}
}

}
9 changes: 9 additions & 0 deletions src/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ enum filterTypes {
MAXSIZE = FLAG(11),
QUERY = FLAG(12),
NAME = FLAG(13),
CATEGORY = FLAG(14),
};

Filter& Filter::local(bool accept)
Expand Down Expand Up @@ -443,6 +444,13 @@ Filter& Filter::rejectTags(std::vector<std::string> tags)
return *this;
}

Filter& Filter::category(std::string category)
{
_category = category;
activeFilters |= CATEGORY;
return *this;
}

Filter& Filter::lang(std::string lang)
{
_lang = lang;
Expand Down Expand Up @@ -502,6 +510,7 @@ bool Filter::accept(const Book& book) const
FILTER(_NOREMOTE, !remote)

FILTER(MAXSIZE, book.getSize() <= _maxSize)
FILTER(CATEGORY, book.getCategory() == _category)
FILTER(LANG, book.getLanguage() == _lang)
FILTER(_PUBLISHER, book.getPublisher() == _publisher)
FILTER(_CREATOR, book.getCreator() == _creator)
Expand Down
5 changes: 3 additions & 2 deletions src/opds_dumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ std::string gen_date_str()
std::stringstream is;
is << std::setw(2) << std::setfill('0')
<< 1900+tm->tm_year << "-"
<< std::setw(2) << std::setfill('0') << tm->tm_mon << "-"
<< std::setw(2) << std::setfill('0') << tm->tm_mon+1 << "-"
<< std::setw(2) << std::setfill('0') << tm->tm_mday << "T"
<< std::setw(2) << std::setfill('0') << tm->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << tm->tm_min << ":"
Expand All @@ -54,7 +54,7 @@ std::string gen_date_str()
static std::string gen_date_from_yyyy_mm_dd(const std::string& date)
{
std::stringstream is;
is << date << "T00:00::00:Z";
is << date << "T00:00::00Z";
return is.str();
}

Expand All @@ -77,6 +77,7 @@ pugi::xml_node OPDSDumper::handleBook(Book book, pugi::xml_node root_node) {
ADD_TEXT_ENTRY(entry_node, "updated", gen_date_from_yyyy_mm_dd(book.getDate()));
ADD_TEXT_ENTRY(entry_node, "name", book.getName());
ADD_TEXT_ENTRY(entry_node, "flavour", book.getFlavour());
ADD_TEXT_ENTRY(entry_node, "category", book.getCategory());
ADD_TEXT_ENTRY(entry_node, "tags", book.getTags());
ADD_TEXT_ENTRY(entry_node, "articleCount", to_string(book.getArticleCount()));
ADD_TEXT_ENTRY(entry_node, "mediaCount", to_string(book.getMediaCount()));
Expand Down
31 changes: 21 additions & 10 deletions src/server/internalServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,22 @@ std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& r
uuid = zim::Uuid::generate(host);
bookIdsToDump = mp_library->filter(kiwix::Filter().valid(true).local(true).remote(true));
} else if (url == "search") {
bookIdsToDump = search_catalog(request, opdsDumper);
uuid = zim::Uuid::generate();
}

opdsDumper.setId(kiwix::to_string(uuid));
auto response = ContentResponse::build(
*this,
opdsDumper.dumpOPDSFeed(bookIdsToDump),
"application/atom+xml; profile=opds-catalog; kind=acquisition; charset=utf-8");
return std::move(response);
}

std::vector<std::string>
InternalServer::search_catalog(const RequestContext& request,
kiwix::OPDSDumper& opdsDumper)
{
auto filter = kiwix::Filter().valid(true).local(true).remote(true);
string query("<Empty query>");
size_t count(10);
Expand All @@ -682,6 +698,9 @@ std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& r
try {
filter.name(request.get_argument("name"));
} catch (const std::out_of_range&) {}
try {
filter.category(request.get_argument("category"));
} catch (const std::out_of_range&) {}
try {
filter.lang(request.get_argument("lang"));
} catch (const std::out_of_range&) {}
Expand All @@ -698,22 +717,14 @@ std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& r
filter.rejectTags(kiwix::split(request.get_argument("notag"), ";"));
} catch (...) {}
opdsDumper.setTitle("Search result for " + query);
uuid = zim::Uuid::generate();
bookIdsToDump = mp_library->filter(filter);
std::vector<std::string> bookIdsToDump = mp_library->filter(filter);
auto totalResults = bookIdsToDump.size();
bookIdsToDump.erase(bookIdsToDump.begin(), bookIdsToDump.begin()+startIndex);
if (count>0 && bookIdsToDump.size() > count) {
bookIdsToDump.resize(count);
}
opdsDumper.setOpenSearchInfo(totalResults, startIndex, bookIdsToDump.size());
}

opdsDumper.setId(kiwix::to_string(uuid));
auto response = ContentResponse::build(
*this,
opdsDumper.dumpOPDSFeed(bookIdsToDump),
"application/atom+xml; profile=opds-catalog; kind=acquisition; charset=utf-8");
return std::move(response);
return bookIdsToDump;
}

namespace
Expand Down
4 changes: 4 additions & 0 deletions src/server/internalServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace kiwix {
typedef kainjow::mustache::data MustacheData;

class Entry;
class OPDSDumper;

class InternalServer {
public:
Expand Down Expand Up @@ -79,6 +80,9 @@ class InternalServer {
std::unique_ptr<Response> handle_captured_external(const RequestContext& request);
std::unique_ptr<Response> handle_content(const RequestContext& request);

std::vector<std::string> search_catalog(const RequestContext& request,
kiwix::OPDSDumper& opdsDumper);

MustacheData get_default_data() const;
MustacheData homepage_data() const;

Expand Down
1 change: 1 addition & 0 deletions src/wrapper/java/book.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ GETTER(jstring, getDate)
GETTER(jstring, getUrl)
GETTER(jstring, getName)
GETTER(jstring, getFlavour)
GETTER(jstring, getCategory)
GETTER(jstring, getTags)
GETTER(jlong, getArticleCount)
GETTER(jlong, getMediaCount)
Expand Down
1 change: 1 addition & 0 deletions src/wrapper/java/org/kiwix/kiwixlib/Book.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Book
public native String getUrl();
public native String getName();
public native String getFlavour();
public native String getCategory();
public native String getTags();
/**
* Return the value associated to the tag tagName
Expand Down
Loading

0 comments on commit f7c867f

Please sign in to comment.