mirror of
https://github.com/standardebooks/web.git
synced 2025-07-13 01:52:02 -04:00
Update generate-opds script to use the web library and templates to generate feeds
This commit is contained in:
parent
86f3adca36
commit
7a043c3e85
2 changed files with 44 additions and 123 deletions
|
@ -4,144 +4,30 @@ $options = getopt("", $longopts);
|
||||||
$webRoot = $options["webroot"] ?? "/standardebooks.org/web";
|
$webRoot = $options["webroot"] ?? "/standardebooks.org/web";
|
||||||
$webUrl = $options["weburl"] ?? "https://standardebooks.org";
|
$webUrl = $options["weburl"] ?? "https://standardebooks.org";
|
||||||
|
|
||||||
|
require_once($webRoot . '/lib/Core.php');
|
||||||
|
|
||||||
$updatedTimestamp = gmdate('Y-m-d\TH:i:s\Z');
|
$updatedTimestamp = gmdate('Y-m-d\TH:i:s\Z');
|
||||||
|
|
||||||
$contentFiles = explode("\n", trim(shell_exec('find ' . escapeshellarg($webRoot . '/www/ebooks/') . ' -name "content.opf" | sort') ?? ''));
|
$contentFiles = explode("\n", trim(shell_exec('find ' . escapeshellarg($webRoot . '/www/ebooks/') . ' -name "content.opf" | sort') ?? ''));
|
||||||
$sortedContentFiles = [];
|
$sortedContentFiles = [];
|
||||||
|
|
||||||
|
$allFeedEbooks = '';
|
||||||
|
|
||||||
foreach($contentFiles as $path){
|
foreach($contentFiles as $path){
|
||||||
if($path == '')
|
if($path == '')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$xml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', file_get_contents($path) ?: ''));
|
$ebookWwwFilesystemPath = preg_replace('|/src/.+|ius', '', $path) ?? '';
|
||||||
$xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
$ebook = new Ebook($ebookWwwFilesystemPath);
|
||||||
|
|
||||||
$updated = $xml->xpath('/package/metadata/meta[@property="dcterms:modified"]') ?: [];
|
$sortedContentFiles[$ebook->ModifiedTimestamp->format('Y-m-dTH:i:sZ') . ' ' . $ebook->Identifier] = $ebook;
|
||||||
$identifier = $xml->xpath('/package/metadata/dc:identifier') ?: [];
|
|
||||||
|
|
||||||
if(sizeof($identifier) > 0 && sizeof($updated) > 0){
|
|
||||||
$sortedContentFiles[(string)$updated[0] . ' ' . $identifier[0]] = $xml;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
krsort($sortedContentFiles);
|
krsort($sortedContentFiles);
|
||||||
|
|
||||||
ob_start();
|
$url = SITE_URL . '/opds/all';
|
||||||
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
|
||||||
|
|
||||||
/* Notes:
|
$feed = Template::OpdsFeed(['id' => $url, 'url' => $url, 'title' => 'All Standard Ebooks', 'updatedTimestamp' => $updatedTimestamp, 'isCrawlable' => true, 'entries' => $sortedContentFiles]);
|
||||||
|
|
||||||
- *All* OPDS feeds must contain a rel="crawlable" link pointing to the /opds/all feed
|
|
||||||
|
|
||||||
- The <fh:complete/> element is required to note this as a "Complete Acquisition Feeds"; see https://specs.opds.io/opds-1.2#25-complete-acquisition-feeds
|
|
||||||
|
|
||||||
*/
|
|
||||||
?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/" xmlns:fh="http://purl.org/syndication/history/1.0">
|
|
||||||
<id><?= $webUrl ?>/opds/all</id>
|
|
||||||
<link href="<?= $webUrl ?>/opds/all" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
|
||||||
<link href="<?= $webUrl ?>/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
|
||||||
<link href="<?= $webUrl ?>/opds/all" rel="crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
|
||||||
<link href="<?= $webUrl ?>/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml" />
|
|
||||||
<title>All Standard Ebooks</title>
|
|
||||||
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
|
|
||||||
<icon><?= $webUrl ?>/images/logo.png</icon>
|
|
||||||
<updated><?= $updatedTimestamp ?></updated>
|
|
||||||
<fh:complete/>
|
|
||||||
<author>
|
|
||||||
<name>Standard Ebooks</name>
|
|
||||||
<uri><?= $webUrl ?></uri>
|
|
||||||
</author>
|
|
||||||
<? foreach($sortedContentFiles as $xml){
|
|
||||||
|
|
||||||
$authors = array();
|
|
||||||
$temp = $xml->xpath('/package/metadata/dc:identifier') ?: [];
|
|
||||||
$identifier = (string)array_shift($temp);
|
|
||||||
$url = preg_replace('/^url:/ius', '', $identifier) ?? '';
|
|
||||||
$url = preg_replace('/^https:\/\/standardebooks\.org/ius', $webUrl, $url) ?? '';
|
|
||||||
$relativeUrl = preg_replace('/^' . preg_quote($webUrl, '/') . '/ius', '', $url) ?? '';
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/dc:title') ?: [];
|
|
||||||
$title = array_shift($temp);
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/meta[@property="se:long-description"]') ?: [];
|
|
||||||
$longDescription = array_shift($temp);
|
|
||||||
|
|
||||||
$authors = $xml->xpath('/package/metadata/dc:creator') ?: [];
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/dc:date') ?: [];
|
|
||||||
$published = array_shift($temp);
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/dc:language') ?: [];
|
|
||||||
$language = array_shift($temp);
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/meta[@property="dcterms:modified"]') ?: [];
|
|
||||||
$modified = array_shift($temp);
|
|
||||||
|
|
||||||
$temp = $xml->xpath('/package/metadata/dc:description') ?: [];
|
|
||||||
$description = array_shift($temp);
|
|
||||||
|
|
||||||
$subjects = $xml->xpath('/package/metadata/dc:subject') ?: [];
|
|
||||||
|
|
||||||
$sources = $xml->xpath('/package/metadata/dc:source') ?: [];
|
|
||||||
|
|
||||||
$filesystemPath = preg_replace('/\/src\/epub\/content.opf$/ius', '', $path) ?? '';
|
|
||||||
$temp = glob($filesystemPath . '/dist/*.epub');
|
|
||||||
$filename = preg_replace('/^url:https:\/\/standardebooks\.org\/ebooks\//ius', '', $identifier);
|
|
||||||
$epubFilename = str_replace('/', '_', $filename) . '.epub';
|
|
||||||
$kindleFilename = str_replace('/', '_', $filename) . '.azw3';
|
|
||||||
|
|
||||||
?>
|
|
||||||
<entry>
|
|
||||||
<id><?= $url ?></id>
|
|
||||||
<title><?= $title ?></title>
|
|
||||||
<? foreach($authors as $author){
|
|
||||||
$id = '';
|
|
||||||
if($author->attributes() !== null){
|
|
||||||
$id = $author->attributes()->id;
|
|
||||||
}
|
|
||||||
$temp = $xml->xpath('/package/metadata/meta[@property="se:url.encyclopedia.wikipedia"][@refines="#' . $id . '"]') ?: [];
|
|
||||||
$wikiUrl = array_shift($temp);
|
|
||||||
$temp = $xml->xpath('/package/metadata/meta[@property="se:name.person.full-name"][@refines="#' . $id . '"]') ?: [];
|
|
||||||
$fullName = array_shift($temp);
|
|
||||||
$temp = $xml->xpath('/package/metadata/meta[@property="se:url.authority.nacoaf"][@refines="#' . $id . '"]') ?: [];
|
|
||||||
$nacoafLink = array_shift($temp);
|
|
||||||
?>
|
|
||||||
<author>
|
|
||||||
<name><?= $author ?></name>
|
|
||||||
<? if($wikiUrl !== null){ ?><uri><?= $wikiUrl ?></uri><? } ?>
|
|
||||||
<? if($fullName !== null){ ?><schema:alternateName><?= $fullName ?></schema:alternateName><? } ?>
|
|
||||||
<? if($nacoafLink !== null){ ?><schema:sameAs><?= $nacoafLink ?></schema:sameAs><? } ?>
|
|
||||||
</author>
|
|
||||||
<? } ?>
|
|
||||||
<published><?= $published ?></published>
|
|
||||||
<dc:issued><?= $published ?></dc:issued>
|
|
||||||
<updated><?= $modified ?></updated>
|
|
||||||
<dc:language><?= $language ?></dc:language>
|
|
||||||
<dc:publisher>Standard Ebooks</dc:publisher>
|
|
||||||
<? foreach($sources as $source){ ?>
|
|
||||||
<dc:source><?= $source ?></dc:source>
|
|
||||||
<? } ?>
|
|
||||||
<rights>Public domain in the United States; original content released to the public domain via the Creative Commons CC0 1.0 Universal Public Domain Dedication</rights>
|
|
||||||
<summary type="text"><?= htmlspecialchars($description, ENT_QUOTES, 'UTF-8') ?></summary>
|
|
||||||
<content type="text/html"><?= $longDescription ?></content>
|
|
||||||
<? foreach($subjects as $subject){ ?>
|
|
||||||
<category scheme="http://purl.org/dc/terms/LCSH" term="<?= htmlspecialchars($subject, ENT_QUOTES, 'UTF-8') ?>"/>
|
|
||||||
<? } ?>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/cover.jpg" rel="http://opds-spec.org/image" type="image/jpeg"/>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/cover-thumbnail.jpg" rel="http://opds-spec.org/image/thumbnail" type="image/jpeg"/>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/<?= $epubFilename ?>" rel="http://opds-spec.org/acquisition/open-access" type="application/epub+zip" title="Recommended compatible epub"/>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/<?= $epubFilename ?>3" rel="http://opds-spec.org/acquisition/open-access" type="application/epub+zip" title="epub"/>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/<?= preg_replace('/\.epub$/ius', '.kepub.epub', $epubFilename) ?>" rel="http://opds-spec.org/acquisition/open-access" type="application/kepub+zip" title="Kobo Kepub epub"/>
|
|
||||||
<link href="<?= $relativeUrl ?>/dist/<?= $kindleFilename ?>" rel="http://opds-spec.org/acquisition/open-access" type="application/x-mobipocket-ebook" title="Amazon Kindle azw3"/>
|
|
||||||
</entry>
|
|
||||||
<? } ?>
|
|
||||||
</feed>
|
|
||||||
<?
|
|
||||||
|
|
||||||
// Print the "all feed" to file
|
|
||||||
$feed = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
|
|
||||||
$tempFilename = tempnam('/tmp/', 'se-opds-');
|
$tempFilename = tempnam('/tmp/', 'se-opds-');
|
||||||
|
|
||||||
|
|
35
templates/OpdsFeed.php
Normal file
35
templates/OpdsFeed.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?
|
||||||
|
|
||||||
|
/* Notes:
|
||||||
|
|
||||||
|
- *All* OPDS feeds must contain a rel="crawlable" link pointing to the /opds/all feed
|
||||||
|
|
||||||
|
- The <fh:complete/> element is required to note this as a "Complete Acquisition Feeds"; see https://specs.opds.io/opds-1.2#25-complete-acquisition-feeds
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!isset($isCrawlable)){
|
||||||
|
$isCrawlable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||||
|
?>
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/" xmlns:fh="http://purl.org/syndication/history/1.0">
|
||||||
|
<id><?= $id ?></id>
|
||||||
|
<link href="<?= $url ?>" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||||
|
<link href="<?= SITE_URL ?>/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||||
|
<link href="<?= SITE_URL ?>/opds/all" rel="crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||||
|
<link href="<?= SITE_URL ?>/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml" />
|
||||||
|
<title><?= $title ?></title>
|
||||||
|
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
|
||||||
|
<icon><?= SITE_URL ?>/images/logo.png</icon>
|
||||||
|
<updated><?= $updatedTimestamp ?></updated>
|
||||||
|
<? if($isCrawlable){ ?><fh:complete/><? } ?>
|
||||||
|
<author>
|
||||||
|
<name>Standard Ebooks</name>
|
||||||
|
<uri><?= SITE_URL ?></uri>
|
||||||
|
</author>
|
||||||
|
<? foreach($entries as $ebook){ ?>
|
||||||
|
<?= Template::OpdsEntry(['ebook' => $ebook]) ?>
|
||||||
|
<? } ?>
|
||||||
|
</feed>
|
Loading…
Add table
Add a link
Reference in a new issue