mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
parent
7ed0c98bab
commit
39798e6a5c
114
src/calibre/library/server/ajax.py
Normal file
114
src/calibre/library/server/ajax.py
Normal file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import json
|
||||
from functools import wraps
|
||||
|
||||
import cherrypy
|
||||
|
||||
from calibre.utils.date import isoformat
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.ebooks.metadata.book.json_codec import JsonCodec
|
||||
|
||||
class Endpoint(object): # {{{
|
||||
'Manage mime-type json serialization, etc.'
|
||||
|
||||
def __init__(self, mimetype='application/json; charset=utf-8',
|
||||
set_last_modified=True):
|
||||
self.mimetype = mimetype
|
||||
self.set_last_modified = set_last_modified
|
||||
|
||||
def __call__(eself, func):
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
# Remove AJAX caching disabling jquery workaround arg
|
||||
# This arg is put into AJAX queries by jQuery to prevent
|
||||
# caching in the browser. We dont want it passed to the wrapped
|
||||
# function
|
||||
kwargs.pop('_', None)
|
||||
|
||||
ans = func(self, *args, **kwargs)
|
||||
cherrypy.response.headers['Content-Type'] = eself.mimetype
|
||||
if eself.set_last_modified:
|
||||
updated = self.db.last_modified()
|
||||
cherrypy.response.headers['Last-Modified'] = \
|
||||
self.last_modified(max(updated, self.build_time))
|
||||
if 'application/json' in eself.mimetype:
|
||||
ans = json.dumps(ans, indent=2,
|
||||
ensure_ascii=False).encode('utf-8')
|
||||
return ans
|
||||
|
||||
return wrapper
|
||||
# }}}
|
||||
|
||||
class AjaxServer(object):
|
||||
|
||||
def __init__(self):
|
||||
self.ajax_json_codec = JsonCodec()
|
||||
|
||||
def add_routes(self, connect):
|
||||
base_href = '/ajax'
|
||||
connect('ajax_book', base_href+'/book/{book_id}', self.ajax_book)
|
||||
|
||||
# Get book metadata {{{
|
||||
@Endpoint()
|
||||
def ajax_book(self, book_id):
|
||||
cherrypy.response.headers['Content-Type'] = \
|
||||
'application/json; charset=utf-8'
|
||||
try:
|
||||
book_id = int(book_id)
|
||||
mi = self.db.get_metadata(book_id, index_is_id=True)
|
||||
except:
|
||||
raise cherrypy.HTTPError(404, 'No book with id: %r'%book_id)
|
||||
try:
|
||||
mi.rating = mi.rating/2.
|
||||
except:
|
||||
mi.rating = 0.0
|
||||
cherrypy.response.timeout = 3600
|
||||
cherrypy.response.headers['Last-Modified'] = \
|
||||
self.last_modified(mi.last_modified)
|
||||
|
||||
data = self.ajax_json_codec.encode_book_metadata(mi)
|
||||
for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime',
|
||||
'rights', 'book_producer'):
|
||||
data.pop(x, None)
|
||||
|
||||
def absurl(url):
|
||||
return self.opts.url_prefix + url
|
||||
|
||||
data['cover'] = absurl(u'/get/cover/%d'%book_id)
|
||||
data['thumbnail'] = absurl(u'/get/thumb/%d'%book_id)
|
||||
mi.format_metadata = {k:dict(v) for k, v in
|
||||
mi.format_metadata.iteritems()}
|
||||
for v in mi.format_metadata.itervalues():
|
||||
mtime = v.get('mtime', None)
|
||||
if mtime is not None:
|
||||
v['mtime'] = isoformat(mtime, as_utc=True)
|
||||
data['format_metadata'] = mi.format_metadata
|
||||
fmts = set(x.lower() for x in mi.format_metadata.iterkeys())
|
||||
pf = prefs['output_format'].lower()
|
||||
other_fmts = list(fmts)
|
||||
try:
|
||||
fmt = pf if pf in fmts else other_fmts[0]
|
||||
except:
|
||||
fmt = None
|
||||
if fmts and fmt:
|
||||
other_fmts = [x for x in fmts if x != fmt]
|
||||
data['formats'] = sorted(fmts)
|
||||
if fmt:
|
||||
data['main_format'] = {fmt: absurl(u'/get/%s/%d'%(fmt, book_id))}
|
||||
else:
|
||||
data['main_format'] = None
|
||||
data['other_formats'] = {fmt: absurl(u'/get/%s/%d'%(fmt, book_id)) for fmt
|
||||
in other_fmts}
|
||||
|
||||
return data
|
||||
# }}}
|
||||
|
@ -24,9 +24,9 @@ from calibre.library.server.xml import XMLServer
|
||||
from calibre.library.server.opds import OPDSServer
|
||||
from calibre.library.server.cache import Cache
|
||||
from calibre.library.server.browse import BrowseServer
|
||||
from calibre.library.server.ajax import AjaxServer
|
||||
from calibre.utils.search_query_parser import saved_searches
|
||||
from calibre import prints
|
||||
from calibre.ebooks.metadata.book.json_codec import JsonCodec
|
||||
|
||||
|
||||
class DispatchController(object): # {{{
|
||||
@ -100,7 +100,7 @@ cherrypy.engine.bonjour = BonJour(cherrypy.engine)
|
||||
# }}}
|
||||
|
||||
class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
||||
BrowseServer):
|
||||
BrowseServer, AjaxServer):
|
||||
|
||||
server_name = __appname__ + '/' + __version__
|
||||
|
||||
@ -164,11 +164,11 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
|
||||
self.__dispatcher__ = DispatchController(self.opts.url_prefix, wsgi)
|
||||
for x in self.__class__.__bases__:
|
||||
if hasattr(x, 'add_routes'):
|
||||
x.__init__(self)
|
||||
x.add_routes(self, self.__dispatcher__)
|
||||
root_conf = self.config.get('/', {})
|
||||
root_conf['request.dispatch'] = self.__dispatcher__.dispatcher
|
||||
self.config['/'] = root_conf
|
||||
self.json_codec = JsonCodec()
|
||||
|
||||
def set_database(self, db):
|
||||
self.db = db
|
||||
|
@ -5,12 +5,12 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re, os, posixpath, json
|
||||
import re, os, posixpath
|
||||
|
||||
import cherrypy
|
||||
|
||||
from calibre import fit_image, guess_type
|
||||
from calibre.utils.date import fromtimestamp, isoformat
|
||||
from calibre.utils.date import fromtimestamp
|
||||
from calibre.library.caches import SortKeyGenerator
|
||||
from calibre.library.save_to_disk import find_plugboard
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
@ -18,7 +18,6 @@ from calibre.utils.magick.draw import (save_cover_data_to, Image,
|
||||
thumbnail as generate_thumbnail)
|
||||
from calibre.utils.filenames import ascii_filename
|
||||
from calibre.ebooks.metadata.opf2 import metadata_to_opf
|
||||
from calibre.utils.config import prefs
|
||||
|
||||
plugboard_content_server_value = 'content_server'
|
||||
plugboard_content_server_formats = ['epub']
|
||||
@ -94,7 +93,7 @@ class ContentServer(object):
|
||||
if what == 'opf':
|
||||
return self.get_metadata_as_opf(id)
|
||||
if what == 'json':
|
||||
return self.get_metadata_as_json(id)
|
||||
raise cherrypy.InternalRedirect('/ajax/book/%d'%id)
|
||||
return self.get_format(id, what)
|
||||
|
||||
def static(self, name):
|
||||
@ -196,51 +195,6 @@ class ContentServer(object):
|
||||
|
||||
return data
|
||||
|
||||
def get_metadata_as_json(self, id_):
|
||||
cherrypy.response.headers['Content-Type'] = \
|
||||
'application/json; charset=utf-8'
|
||||
mi = self.db.get_metadata(id_, index_is_id=True)
|
||||
try:
|
||||
mi.rating = mi.rating/2.
|
||||
except:
|
||||
mi.rating = 0.0
|
||||
cherrypy.response.timeout = 3600
|
||||
cherrypy.response.headers['Last-Modified'] = \
|
||||
self.last_modified(mi.last_modified)
|
||||
|
||||
data = self.json_codec.encode_book_metadata(mi)
|
||||
for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime',
|
||||
'rights', 'book_producer'):
|
||||
data.pop(x, None)
|
||||
|
||||
def absurl(url):
|
||||
return self.opts.url_prefix + url
|
||||
|
||||
data['cover'] = absurl(u'/get/cover/%d'%id_)
|
||||
data['thumbnail'] = absurl(u'/get/thumb/%d'%id_)
|
||||
for v in mi.format_metadata.itervalues():
|
||||
mtime = v.get('mtime', None)
|
||||
if mtime is not None:
|
||||
v['mtime'] = isoformat(mtime, as_utc=True)
|
||||
data['format_metadata'] = mi.format_metadata
|
||||
fmts = set(x.lower() for x in mi.format_metadata.iterkeys())
|
||||
pf = prefs['output_format'].lower()
|
||||
other_fmts = list(fmts)
|
||||
try:
|
||||
fmt = pf if pf in fmts else other_fmts[0]
|
||||
except:
|
||||
fmt = None
|
||||
if fmts and fmt:
|
||||
other_fmts = [x for x in fmts if x != fmt]
|
||||
data['formats'] = sorted(fmts)
|
||||
if fmt:
|
||||
data['main_format'] = {fmt: absurl(u'/get/%s/%d'%(fmt, id_))}
|
||||
else:
|
||||
data['main_format'] = None
|
||||
data['other_formats'] = {fmt: absurl(u'/get/%s/%d'%(fmt, id_)) for fmt
|
||||
in other_fmts}
|
||||
|
||||
return json.dumps(data, indent=2, ensure_ascii=False).encode('utf-8')
|
||||
|
||||
def get_format(self, id, format):
|
||||
format = format.upper()
|
||||
|
Loading…
x
Reference in New Issue
Block a user