mirror of
https://github.com/Yetangitu/owncloud-apps.git
synced 2025-10-02 14:49:17 +02:00
version 0.3:
- added metadata extraction for epub documents, these will now have full entries where metadata is available - metadata is cached in the database - feed 'entry' template updated to 'full entry' according to OPDS v1.1
This commit is contained in:
parent
fdeb32755a
commit
ab06703347
8 changed files with 224 additions and 11 deletions
|
@ -16,7 +16,7 @@ The first method gives you the latest, greatest and potentially buggiest version
|
|||
files_opds
|
||||
----------
|
||||
|
||||
The OPDS catalog app enables Owncloud users to publish a sub-tree of their personal filesystem as an OPDS feed. Since Owncloud currently has limited to no support for metadata, the OPDS entries are rather sparse for now: only title (as in 'filename'), file size, cover image (where available), modification time and content links are provided.
|
||||
The OPDS catalog app enables Owncloud users to publish a sub-tree of their personal filesystem as an OPDS feed. Since Owncloud currently has limited to no support for metadata, these are for now stored in a separate table. As of v0.3 OPDS catalog can extract all relevant metadata from EPUB documents; other document types will appear with sparse entries for now: only title (as in 'filename'), file size, cover image (where available), modification time and content links are provided.
|
||||
|
||||
The root feed links to a hierarchical navigation feed mirroring the directory structure as well as a 'personal bookshelf' containing all downloaded books in order (most recent download first). This 'personal bookshelf' will be empty (0 books) at first. Use the 'Browse catalog' link to download a book and it'll appear on the 'personal bookshelf'. Download another, and it will appear above the one you previously downloaded. This makes it possible to get at books you are in the process of reading from different devices, or to easily re-visit a book you downloaded earlier.
|
||||
|
||||
|
@ -44,6 +44,7 @@ The feed has been tested on these clients:
|
|||
- KyBook on iOS: OK
|
||||
- Marvin on iOS: OK
|
||||
- eBook Search on iOS: browsing works, downloading does not (401 error, 'Unauthorised')
|
||||
- Gecko-based browsers: OK, feed can be browsed and books can be downloaded without additional software.
|
||||
|
||||
|
||||
|
||||
|
|
BIN
dist/files_opds-0.3.tar.gz
vendored
Normal file
BIN
dist/files_opds-0.3.tar.gz
vendored
Normal file
Binary file not shown.
110
files_opds/appinfo/database.xml
Normal file
110
files_opds/appinfo/database.xml
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<database>
|
||||
<name>*dbname*</name>
|
||||
<create>true</create>
|
||||
<overwrite>false</overwrite>
|
||||
<charset>utf8</charset>
|
||||
|
||||
<table>
|
||||
<name>*dbprefix*opds_metadata</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<!-- file ID, maps to OC file ID -->
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<length>11</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- updated (time this record was created) -->
|
||||
<name>updated</name>
|
||||
<type>timestamp</type>
|
||||
<default>1970-01-01 00:00:00</default>
|
||||
<notnull>false</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- date (corresponds to <dc:date> in epub -->
|
||||
<name>date</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>32</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- author(s) -->
|
||||
<name>author</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>256</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- title -->
|
||||
<name>title</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>256</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- language -->
|
||||
<name>language</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- publisher -->
|
||||
<name>publisher</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- ISBN -->
|
||||
<name>isbn</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>16</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- copyright -->
|
||||
<name>copyright</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>128</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- description -->
|
||||
<name>description</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>2048</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<!-- subjects -->
|
||||
<name>subjects</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>1024</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
</database>
|
|
@ -4,7 +4,7 @@
|
|||
<name>OPDS catalog</name>
|
||||
<description>Personal OPDS catalog</description>
|
||||
<licence>AGPL</licence>
|
||||
<version>0.2</version>
|
||||
<version>0.3</version>
|
||||
<author>Frank de Lange</author>
|
||||
<requiremin>7.0</requiremin>
|
||||
<shipped>true</shipped>
|
||||
|
|
|
@ -21,7 +21,7 @@ use \DOMDocument;
|
|||
* based on https://github.com/splitbrain/php-epub-meta
|
||||
*/
|
||||
class Epub {
|
||||
protected $xml;
|
||||
public $xml;
|
||||
protected $xpath;
|
||||
protected $file;
|
||||
protected $meta;
|
||||
|
@ -75,7 +75,7 @@ class Epub {
|
|||
* @brief file name getter
|
||||
* @return string filename
|
||||
*/
|
||||
public static function file() {
|
||||
public function file() {
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ class Epub {
|
|||
*
|
||||
* @return array $authors
|
||||
*/
|
||||
public static function Authors() {
|
||||
public function Authors() {
|
||||
// read current data
|
||||
$rolefix = false;
|
||||
$authors = array();
|
||||
|
@ -127,6 +127,15 @@ class Epub {
|
|||
return $this->get('dc:language');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get date
|
||||
*
|
||||
* @param string $date
|
||||
*/
|
||||
public function Date(){
|
||||
return $this->get('dc:date');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get publisher info
|
||||
*
|
||||
|
|
|
@ -35,6 +35,7 @@ class Files extends \OCA\Files\Helper
|
|||
$entry['preview'] = self::getPreview($i);
|
||||
$entry['thumbnail'] = self::getThumbnail($i);
|
||||
$entry['humansize'] = \OC_Helper::humanFileSize($i['size']);
|
||||
$entry['meta'] = Util::getMeta($i['fileid']);
|
||||
} else {
|
||||
$entry['icon'] = self::determineIcon($i);
|
||||
}
|
||||
|
|
|
@ -148,4 +148,76 @@ class Util
|
|||
public static function logWarn($msg) {
|
||||
\OCP\Util::writeLog('files_opds', $msg, \OCP\Util::WARN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get metadata for fileid
|
||||
*
|
||||
* Long function, to be split later
|
||||
*
|
||||
* @param int $id fileid
|
||||
* @return array of metadata
|
||||
*/
|
||||
public static function getMeta($id) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*opds_metadata` WHERE id = ?';
|
||||
$args = array($id);
|
||||
$query = \OCP\DB::prepare($sql);
|
||||
$result = $query->execute($args);
|
||||
if ($row = $result->fetchRow()) {
|
||||
return $row;
|
||||
} else {
|
||||
/* start with empty values, except for id. This way, files only get
|
||||
* scanned once, even if they don't contain valid metadate.
|
||||
*/
|
||||
$meta = array();
|
||||
$meta['id'] = $id;
|
||||
$meta['updated'] = date("Y-m-d\TH:i:sP");
|
||||
$meta['date'] = '';
|
||||
$meta['author'] = '';
|
||||
$meta['title'] = '';
|
||||
$meta['language'] = '';
|
||||
$meta['publisher'] = '';
|
||||
$meta['isbn'] = '';
|
||||
$meta['copyright'] = '';
|
||||
$meta['description'] = '';
|
||||
$meta['subjects'] = '';
|
||||
|
||||
$path = \OC\Files\Filesystem::getLocalFile(\OC\Files\Filesystem::getPath($id));
|
||||
switch (strtolower(substr(strrchr($path, "."), 1))) {
|
||||
case 'epub':
|
||||
$epub = new Epub($path);
|
||||
$meta['author'] = json_encode($epub->Authors());
|
||||
$meta['title'] = $epub->Title();
|
||||
$meta['date'] = $epub->Date();
|
||||
$meta['publisher'] = $epub->Publisher();
|
||||
$meta['copyright'] = $epub->Copyright();
|
||||
$meta['language'] = $epub->Language();
|
||||
$meta['description'] = strip_tags($epub->Description());
|
||||
$meta['isbn'] = $epub->ISBN();
|
||||
$meta['subjects'] = $epub->Subjects();
|
||||
break;
|
||||
default:
|
||||
// set title to filename minus extension
|
||||
$info = pathinfo($path);
|
||||
$meta['title'] = basename($path,'.'.$info['extension']);
|
||||
break;
|
||||
}
|
||||
$sql = "INSERT INTO *PREFIX*opds_metadata (`id`, `updated`, `date`, `author`, `title`, `language`, `publisher`, `isbn`, `copyright`, `description`, `subjects`) VALUES (?,?,?,?,?,?,?,?,?,?,?)";
|
||||
$args = array(
|
||||
$meta['id'],
|
||||
$meta['updated'],
|
||||
$meta['date'],
|
||||
$meta['author'],
|
||||
$meta['title'],
|
||||
$meta['language'],
|
||||
$meta['publisher'],
|
||||
$meta['isbn'],
|
||||
$meta['copyright'],
|
||||
$meta['description'],
|
||||
$meta['subjects']
|
||||
);
|
||||
$query = \OCP\DB::prepare($sql);
|
||||
$result = $query->execute($args);
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,10 +59,19 @@ echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|||
|
||||
<?php foreach ($_['bookshelf'] as $file): ?>
|
||||
<entry>
|
||||
<title><?php p($file['name']); ?></title>
|
||||
<updated><?php p(date("Y-m-d\TH:i:sP", $file['mtime'])); ?></updated>
|
||||
<title><?php p($file['meta']['title']); ?></title>
|
||||
<updated><?php p(date("Y-m-d\TH:i:sP",strtotime($file['meta']['updated']))); ?></updated>
|
||||
<id>id:<?php p($file['id']); ?></id>
|
||||
<dcterms:extent><?php p($file['humansize']); ?></dcterms:extent>
|
||||
<dc:language><?php p($file['meta']['language']); ?></dc:language>
|
||||
<?php foreach (json_decode($file['meta']['author'],true) as $author): ?>
|
||||
<author>
|
||||
<name><?php p($author); ?></name>
|
||||
</author>
|
||||
<dc:identifier>urn:isbn:<?php p($file['meta']['isbn']); ?></dc:identifier>
|
||||
<dc:publisher><?php p($file['meta']['publisher']); ?></dc:publisher>
|
||||
<dc:issued><?php p($file['meta']['date']); ?></dc:issued>
|
||||
<?php endforeach; ?>
|
||||
<link type="<?php p($file['mimetype']); ?>"
|
||||
rel="alternate"
|
||||
href="?id=<?php p($file['id']); ?>"/>
|
||||
|
@ -75,7 +84,8 @@ echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|||
<link href="<?php p($file['thumbnail']); ?>"
|
||||
rel="http://opds-spec.org/image/thumbnail"
|
||||
type="image/jpeg" />
|
||||
<content type="text"><?php p(formatMetadata($file['humansize'],$file['mimetype'],$file['name'])); ?></content>
|
||||
<summary type="text"><?php p(formatMetadata($file['humansize'],$file['mimetype'],$file['name'])); ?></summary>
|
||||
<content type="text"><?php p("Size: " . $file['humansize'] . "\n\n"); ?><?php p($file['meta']['description']); ?></content>
|
||||
</entry>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
|
@ -95,10 +105,19 @@ echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|||
</entry>
|
||||
<?php else: ?>
|
||||
<entry>
|
||||
<title><?php p($file['name']); ?></title>
|
||||
<updated><?php p(date("Y-m-d\TH:i:sP", $file['mtime'])); ?></updated>
|
||||
<title><?php p($file['meta']['title']); ?></title>
|
||||
<updated><?php p(date("Y-m-d\TH:i:sP",strtotime($file['meta']['updated']))); ?></updated>
|
||||
<id>id:<?php p($file['id']); ?></id>
|
||||
<dcterms:extent><?php p($file['humansize']); ?></dcterms:extent>
|
||||
<dc:language><?php p($file['meta']['language']); ?></dc:language>
|
||||
<?php foreach (json_decode($file['meta']['author'],true) as $author): ?>
|
||||
<author>
|
||||
<name><?php p($author); ?></name>
|
||||
</author>
|
||||
<dc:identifier>urn:isbn:<?php p($file['meta']['isbn']); ?></dc:identifier>
|
||||
<dc:publisher><?php p($file['meta']['publisher']); ?></dc:publisher>
|
||||
<dc:issued><?php p($file['meta']['date']); ?></dc:issued>
|
||||
<?php endforeach; ?>
|
||||
<link type="<?php p($file['mimetype']); ?>"
|
||||
rel="alternate"
|
||||
href="?id=<?php p($file['id']); ?>"/>
|
||||
|
@ -111,7 +130,8 @@ echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|||
<link href="<?php p($file['thumbnail']); ?>"
|
||||
rel="http://opds-spec.org/image/thumbnail"
|
||||
type="image/jpeg" />
|
||||
<content type="text"><?php p(formatMetadata($file['humansize'],$file['mimetype'],$file['name'])); ?></content>
|
||||
<summary type="text"><?php p(formatMetadata($file['humansize'],$file['mimetype'],$file['name'])); ?></summary>
|
||||
<content type="text"><?php p("Size: " . $file['humansize'] . "\n\n"); ?><?php p($file['meta']['description']); ?></content>
|
||||
</entry>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue