mirror of
https://github.com/standardebooks/web.git
synced 2025-07-09 16:20:27 -04:00
Flesh out OPDS generation backend to be more robust and to support generic Atom feeds
This commit is contained in:
parent
35188195f1
commit
f6df03cfca
23 changed files with 1549 additions and 267 deletions
122
scripts/generate-feeds
Executable file
122
scripts/generate-feeds
Executable file
|
@ -0,0 +1,122 @@
|
|||
#!/usr/bin/php
|
||||
<?
|
||||
require_once('/standardebooks.org/web/lib/Core.php');
|
||||
|
||||
use function Safe\krsort;
|
||||
use function Safe\getopt;
|
||||
use function Safe\preg_replace;
|
||||
use function Safe\sort;
|
||||
|
||||
$longopts = ["webroot:", "weburl:"];
|
||||
$options = getopt("", $longopts);
|
||||
$webRoot = $options["webroot"] ?? "/standardebooks.org/web";
|
||||
$webUrl = $options["weburl"] ?? "https://standardebooks.org";
|
||||
|
||||
$contentFiles = explode("\n", trim(shell_exec('find ' . escapeshellarg($webRoot . '/www/ebooks/') . ' -name "content.opf" | sort') ?? ''));
|
||||
$allEbooks = [];
|
||||
$newestEbooks = [];
|
||||
$subjects = [];
|
||||
$ebooksBySubject = [];
|
||||
$ebooksPerNewestEbooksFeed = 30;
|
||||
|
||||
// Iterate over all ebooks to build the various feeds
|
||||
foreach($contentFiles as $path){
|
||||
if($path == '')
|
||||
continue;
|
||||
|
||||
$ebookWwwFilesystemPath = '';
|
||||
|
||||
try{
|
||||
$ebookWwwFilesystemPath = preg_replace('|/content\.opf|ius', '', $path);
|
||||
|
||||
$ebook = new Ebook($ebookWwwFilesystemPath);
|
||||
|
||||
$allEbooks[$ebook->ModifiedTimestamp->format('Y-m-d\TH:i:s\Z') . ' ' . $ebook->Identifier] = $ebook;
|
||||
$newestEbooks[$ebook->Timestamp->format('Y-m-d\TH:i:s\Z') . ' ' . $ebook->Identifier] = $ebook;
|
||||
|
||||
foreach($ebook->Tags as $tag){
|
||||
// Add the book's subjects to the main subjects list
|
||||
if(!in_array($tag->Name, $subjects)){
|
||||
$subjects[] = $tag->Name;
|
||||
}
|
||||
|
||||
// Sort this ebook by subject
|
||||
$ebooksBySubject[$tag->Name][$ebook->Timestamp->format('Y-m-d\TH:i:s\Z') . ' ' . $ebook->Identifier] = $ebook;
|
||||
}
|
||||
}
|
||||
catch(\Exception $ex){
|
||||
print('Failed to generate OPDS entry for `' . $ebookWwwFilesystemPath . '`. Exception: ' . $ex->getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$now = new DateTime();
|
||||
|
||||
// Create OPDS feeds
|
||||
$opdsRootEntries = [
|
||||
new OpdsNavigationEntry(
|
||||
'/opds/new-releases',
|
||||
'http://opds-spec.org/sort/new',
|
||||
'acquisition',
|
||||
$now,
|
||||
'Newest ' . number_format($ebooksPerNewestEbooksFeed) . ' Standard Ebooks',
|
||||
'A list of the ' . number_format($ebooksPerNewestEbooksFeed) . ' newest Standard Ebooks, most-recently-released first.'),
|
||||
new OpdsNavigationEntry(
|
||||
'/opds/subjects',
|
||||
'subsection',
|
||||
'navigation',
|
||||
$now,
|
||||
'Standard Ebooks by Subject',
|
||||
'Browse Standard Ebooks by subject.'),
|
||||
new OpdsNavigationEntry(
|
||||
'/opds/all',
|
||||
'http://opds-spec.org/crawlable',
|
||||
'acquisition',
|
||||
$now,
|
||||
'All Standard Ebooks',
|
||||
'A list of all Standard Ebooks, most-recently-updated first. This is a Complete Acquisition Feed as defined in OPDS 1.2 §2.5.')
|
||||
];
|
||||
|
||||
$opdsRoot = new OpdsNavigationFeed('/opds', 'Standard Ebooks', WEB_ROOT . '/opds/index.xml', $opdsRootEntries, null);
|
||||
$opdsRoot->Save();
|
||||
|
||||
// Create the subjects navigation document
|
||||
sort($subjects);
|
||||
$subjectNavigationEntries = [];
|
||||
foreach($subjects as $subject){
|
||||
$summary = number_format(sizeof($ebooksBySubject[$subject])) . ' Standard Ebook';
|
||||
if(sizeof($ebooksBySubject[$subject]) != 1){
|
||||
$summary .= 's';
|
||||
}
|
||||
$summary .= ' tagged with “' . strtolower($subject) . ',” most-recently-released first.';
|
||||
|
||||
// We leave the updated timestamp blank, as it will be filled in when we generate the individual feeds
|
||||
$subjectNavigationEntries[] = new OpdsNavigationEntry('/opds/subjects/' . Formatter::MakeUrlSafe($subject), 'subsection', 'navigation', $now, $subject, $summary);
|
||||
}
|
||||
$subjectsFeed = new OpdsNavigationFeed('/opds/subjects', 'Standard Ebooks by Subject', WEB_ROOT . '/opds/subjects/index.xml', $subjectNavigationEntries, $opdsRoot);
|
||||
$subjectsFeed->Save();
|
||||
|
||||
// Now generate each individual subject feed
|
||||
foreach($ebooksBySubject as $subject => $ebooks){
|
||||
krsort($ebooks);
|
||||
$subjectFeed = new OpdsAcquisitionFeed('/opds/subjects/' . Formatter::MakeUrlSafe((string)$subject), (string)$subject, WEB_ROOT . '/opds/subjects/' . Formatter::MakeUrlSafe((string)$subject) . '.xml', $ebooks, $subjectsFeed);
|
||||
$subjectFeed->Save();
|
||||
}
|
||||
|
||||
// Create the 'all' feed
|
||||
krsort($allEbooks);
|
||||
$allFeed = new OpdsAcquisitionFeed('/opds/all', 'All Standard Ebooks', WEB_ROOT . '/opds/all.xml', $allEbooks, $opdsRoot, true);
|
||||
$allFeed->Save();
|
||||
|
||||
// Create the 'newest' feed
|
||||
krsort($newestEbooks);
|
||||
$newestEbooks = array_slice($newestEbooks, 0, $ebooksPerNewestEbooksFeed);
|
||||
$newestFeed = new OpdsAcquisitionFeed('/opds/new-releases', 'Newest ' . number_format($ebooksPerNewestEbooksFeed) . ' Standard Ebooks', WEB_ROOT . '/opds/new-releases.xml', $newestEbooks, $opdsRoot);
|
||||
$newestFeed->Save();
|
||||
|
||||
// Now create RSS feeds
|
||||
|
||||
// Create the 'newest' feed
|
||||
$newestFeed = new RssFeed('/rss/new-releases', 'Newest ' . number_format($ebooksPerNewestEbooksFeed) . ' Standard Ebooks', WEB_ROOT . '/rss/new-releases.xml', 'A list of the ' . number_format($ebooksPerNewestEbooksFeed) . ' latest Standard Ebooks ebook releases, most-recently-released first.', $newestEbooks);
|
||||
$newestFeed->Save();
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue