rip out all mobile site remnants
parent
9c8f030218
commit
c2833335b9
|
@ -43,7 +43,7 @@ VALID_PROTOCOLS = ('http', 'https')
|
|||
|
||||
MEDIATYPE_TO_FORMAT = {
|
||||
'text/html' : 'html',
|
||||
mt.mobile : 'mobile',
|
||||
mt.mobile : 'html',
|
||||
mt.opds : 'opds',
|
||||
mt.json : 'json',
|
||||
}
|
||||
|
@ -101,54 +101,6 @@ class ClassAttr (object):
|
|||
return b in self.value
|
||||
|
||||
|
||||
class Accumulator (object):
|
||||
"""
|
||||
Thread-safe master/slave counter for statistics collection.
|
||||
|
||||
Many serving threads can increment the master counter
|
||||
while the statistic thread safely reads the slave counter.
|
||||
|
||||
"""
|
||||
|
||||
def __init__ (self):
|
||||
self.master = defaultdict (int)
|
||||
self.slave = defaultdict (int)
|
||||
self.lock = threading.Lock ()
|
||||
|
||||
def increment (self, key):
|
||||
""" Thread-safe increment the master counter. """
|
||||
try:
|
||||
self.lock.acquire ()
|
||||
self.master[key] += 1
|
||||
finally:
|
||||
self.lock.release ()
|
||||
|
||||
def reset (self):
|
||||
""" Copy values to slave counter and reset the master counter. """
|
||||
try:
|
||||
self.lock.acquire ()
|
||||
self.slave = self.master.copy ()
|
||||
self.master.clear ()
|
||||
finally:
|
||||
self.lock.release ()
|
||||
|
||||
def __getitem__ (self, k):
|
||||
""" Read value from the slave counter. """
|
||||
return self.slave[k]
|
||||
|
||||
def iter_results (self):
|
||||
""" Iterate over the slave counters. """
|
||||
|
||||
total_hits = float (sum (self.slave.values ()))
|
||||
if total_hits > 0:
|
||||
for k, v in sorted (self.slave.items (), key = lambda x: -x[1]):
|
||||
yield (k, v, v / total_hits)
|
||||
|
||||
|
||||
formats_acc = Accumulator ()
|
||||
formats_sum_acc = Accumulator ()
|
||||
|
||||
|
||||
class DC (GutenbergDatabaseDublinCore.GutenbergDatabaseDublinCore,
|
||||
DublinCoreI18n.DublinCoreI18nMixin):
|
||||
""" A localized DublinCore. """
|
||||
|
@ -491,12 +443,6 @@ class OpenSearch (object):
|
|||
except ValueError as what:
|
||||
raise cherrypy.HTTPError (400, 'Bad Request. ' + str (what))
|
||||
|
||||
formats_acc.increment (self.format)
|
||||
|
||||
if self.format in ('mobile', 'opds', 'stanza'):
|
||||
formats_sum_acc.increment ('mobile')
|
||||
if self.format == 'html':
|
||||
formats_sum_acc.increment ('html')
|
||||
|
||||
self.file_host = cherrypy.config['file_host']
|
||||
self.now = datetime.datetime.utcnow ().replace (microsecond = 0).isoformat () + 'Z'
|
||||
|
@ -594,7 +540,6 @@ class OpenSearch (object):
|
|||
self.viewport = None
|
||||
|
||||
self.desktop_host = cherrypy.config['host']
|
||||
self.mobile_host = cherrypy.config['host_mobile']
|
||||
|
||||
last_page = max ((self.total_results - 1) // self.items_per_page, 0) # 0-based
|
||||
|
||||
|
@ -608,7 +553,6 @@ class OpenSearch (object):
|
|||
self.show_next_page_link = (self.end_index < self.total_results)
|
||||
|
||||
self.desktop_search = self.url ('search', format = None)
|
||||
self.mobile_search = self.url ('search', format = 'mobile')
|
||||
self.json_search = self.url ('suggest', format = None)
|
||||
|
||||
self.base_url = self.url (host = self.file_host)
|
||||
|
@ -617,7 +561,6 @@ class OpenSearch (object):
|
|||
self.canonical_url = self.url_carry (host = self.file_host, format = None)
|
||||
|
||||
self.desktop_url = self.url_carry (host = self.desktop_host, format = None)
|
||||
self.mobile_url = self.url_carry (host = self.mobile_host, format = 'mobile')
|
||||
|
||||
self.osd_url = self.qualify ('/catalog/osd-books.xml')
|
||||
|
||||
|
@ -704,7 +647,7 @@ class OpenSearch (object):
|
|||
|
||||
# user explicitly requested format
|
||||
if format_:
|
||||
self.format = format_
|
||||
self.format = 'html' if format_ == 'mobile' else format_
|
||||
self.mediatype = mt[format_]
|
||||
self.opensearch_support = 1 if format_ == 'opds' else 2
|
||||
return
|
||||
|
@ -713,32 +656,11 @@ class OpenSearch (object):
|
|||
|
||||
ua = self.user_agent
|
||||
|
||||
# user accessed the www site
|
||||
|
||||
if self.host == cherrypy.config['host']:
|
||||
# but might want the mobile site ...
|
||||
if 'Kindle/' in ua:
|
||||
self.format = 'mobile'
|
||||
self.mediatype = mt.mobile
|
||||
elif 'tolino' in ua:
|
||||
self.format = 'mobile'
|
||||
self.mediatype = mt.mobile
|
||||
elif ua.startswith ('W3C-mobileOK/DDC-1.0'):
|
||||
self.format = 'mobile'
|
||||
self.mediatype = mt.mobile
|
||||
else:
|
||||
self.format = 'html'
|
||||
self.mediatype = 'text/html'
|
||||
return
|
||||
self.format = 'html'
|
||||
self.mediatype = 'text/html'
|
||||
|
||||
# user accessed the mobile site
|
||||
|
||||
mediatype = None
|
||||
|
||||
if self.host == cherrypy.config['host_mobile']:
|
||||
format_ = 'mobile'
|
||||
mediatype = mt.mobile
|
||||
|
||||
# known OPDS consumers
|
||||
# 'stanza' is the older opds-ish format supported by stanza et al.
|
||||
|
||||
|
@ -795,11 +717,6 @@ class OpenSearch (object):
|
|||
mediatype = mt.opds
|
||||
opensearch_support = 1
|
||||
|
||||
# still nothing?
|
||||
if not format_:
|
||||
mediatype = 'text/html'
|
||||
format_ = 'html'
|
||||
|
||||
self.format = format_
|
||||
self.mediatype = mediatype
|
||||
self.opensearch_support = opensearch_support
|
||||
|
|
|
@ -19,7 +19,6 @@ pgdatabase: 'gutenberg'
|
|||
pguser: 'postgres'
|
||||
|
||||
host: 'www.gutenberg.org'
|
||||
host_mobile: 'm.gutenberg.org'
|
||||
host_https: 1
|
||||
file_host: 'www.gutenberg.org'
|
||||
|
||||
|
|
|
@ -87,7 +87,6 @@ def main():
|
|||
'daemonize': False,
|
||||
'pidfile': None,
|
||||
'host': 'localhost',
|
||||
'host_mobile': 'localhost',
|
||||
'file_host': 'localhost',
|
||||
})
|
||||
|
||||
|
|
|
@ -31,9 +31,6 @@ from i18n_tool import ugettext as _
|
|||
# filetypes ignored on desktop site
|
||||
NO_DESKTOP_FILETYPES = 'plucker qioo rdf rst rst.gen rst.master tei cover.medium cover.small'.split ()
|
||||
|
||||
# filetypes shown on mobile site
|
||||
MOBILE_TYPES = (mt.epub, mt.mobi, mt.pdf, 'text/html', mt.html)
|
||||
|
||||
# filetypes which are usually handed over to a separate app on mobile devices
|
||||
HANDOVER_TYPES = (mt.epub, mt.mobi, mt.pdf)
|
||||
|
||||
|
@ -187,44 +184,3 @@ class HTMLFormatter (XMLishFormatter):
|
|||
if showncount == 0:
|
||||
for file_ in dc.files + dc.generated_files:
|
||||
file_.hidden = False
|
||||
|
||||
|
||||
class MobileFormatter (XMLishFormatter):
|
||||
""" Produce HTML output suitable for mobile devices. """
|
||||
|
||||
CONTENT_TYPE = mt.xhtml + '; charset=UTF-8'
|
||||
DOCTYPE = 'html5'
|
||||
|
||||
def __init__ (self):
|
||||
super (MobileFormatter, self).__init__ ()
|
||||
|
||||
|
||||
def get_serializer (self):
|
||||
return genshi.output.HTMLSerializer (doctype = self.DOCTYPE, strip_whitespace = False)
|
||||
|
||||
|
||||
def fix_dc (self, dc, os):
|
||||
""" Add some info to dc for easier templating.
|
||||
|
||||
Also make sure that dc `walks like a cat´. """
|
||||
|
||||
super (MobileFormatter, self).fix_dc (dc, os)
|
||||
|
||||
for file_ in dc.files + dc.generated_files:
|
||||
if len (file_.mediatypes) == 1:
|
||||
type_ = six.text_type (file_.mediatypes[0])
|
||||
m = type_.partition (';')[0]
|
||||
if m in MOBILE_TYPES:
|
||||
cat = BaseSearcher.Cat ()
|
||||
cat.type = file_.mediatypes[0]
|
||||
cat.header = _('Download')
|
||||
cat.title = file_.hr_filetype
|
||||
cat.extra = file_.hr_extent
|
||||
|
||||
cat.charset = file_.encoding
|
||||
cat.url = '/' + file_.filename
|
||||
cat.icon = dc.icon
|
||||
cat.icon2 = 'download'
|
||||
cat.class_ += 'filelink'
|
||||
cat.order = 20
|
||||
os.entries.append (cat)
|
||||
|
|
|
@ -265,7 +265,7 @@ class AuthorPage (SearchPage):
|
|||
os.entries.insert (0, cat)
|
||||
|
||||
# author aliases
|
||||
if os.format in ('html', 'mobile'):
|
||||
if os.format == 'html':
|
||||
rows = BaseSearcher.SQLSearcher.execute (
|
||||
"""SELECT alias AS title FROM aliases
|
||||
WHERE fk_authors = %(fk_authors)s AND alias_heading = 1""",
|
||||
|
|
|
@ -30,7 +30,6 @@ class Start (Page.Page):
|
|||
|
||||
os.search_terms = ''
|
||||
os.title = {
|
||||
'mobile': _('PG Mobile'),
|
||||
'opds': _('Project Gutenberg'),
|
||||
'stanza': _('Project Gutenberg')
|
||||
}.get (os.format, _('Search Project Gutenberg'))
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<script type="text/javascript">//<![CDATA[
|
||||
//<![CDATA[
|
||||
var json_search = "/ebooks/suggest/";
|
||||
var mobile_url = "https://www.gutenberg.org/ebooks/";
|
||||
var canonical_url = "https://www.gutenberg.org/ebooks/";
|
||||
var lang = "en";
|
||||
var fb_lang = "en_US"; /* FB accepts only xx_XX */
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
|
||||
DON'T USE THIS PAGE FOR SCRAPING.
|
||||
|
||||
Seriously. You'll only get your IP blocked.
|
||||
|
||||
Download https://www.gutenberg.org/feeds/catalog.rdf.bz2 instead,
|
||||
which contains *all* Project Gutenberg metadata in one RDF/XML file.
|
||||
|
||||
-->
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:py="http://genshi.edgewall.org/"
|
||||
xmlns:i18n="http://genshi.edgewall.org/i18n"
|
||||
xml:lang="${os.lang}">
|
||||
|
||||
<?python
|
||||
import re
|
||||
|
||||
from libgutenberg import GutenbergGlobals as gg
|
||||
old_header = ''
|
||||
|
||||
def help_page (s = ''):
|
||||
s = s.replace (' ', '_')
|
||||
return '%s#%s' % ('/wiki/Gutenberg:Help_on_Bibliographic_Record_Page', s)
|
||||
?>
|
||||
|
||||
<xi:include href="site-layout.mobile" />
|
||||
|
||||
<head profile="http://a9.com/-/spec/opensearch/1.1/">
|
||||
${site_head ()}
|
||||
|
||||
<title>${os.title}</title>
|
||||
|
||||
<meta name="totalResults" content="${os.total_results}" />
|
||||
<meta name="startIndex" content="${os.start_index}" />
|
||||
<meta name="itemsPerPage" content="${os.items_per_page}" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="content" i18n:comment="On the page of results of a search.">
|
||||
<ol class="results">
|
||||
|
||||
${search_box ()}
|
||||
|
||||
<py:for each="n, e in enumerate (os.entries)">
|
||||
<py:if test="e.header and old_header != e.header">
|
||||
<li class="header">${e.header}</li>
|
||||
</py:if>
|
||||
<?python old_header = e.header ?>
|
||||
|
||||
<py:if test="isinstance (e, bs.DC)">
|
||||
<li class="bibrec">
|
||||
<div class="table">
|
||||
<div class="row">
|
||||
<div class="cell leftcell">
|
||||
<div class="icon icon_${e.icon}" />
|
||||
</div>
|
||||
<div class="cell content">
|
||||
<!--! get coverpage first, it floats to the right -->
|
||||
<img py:if="e.cover_image" class="coverpage"
|
||||
src="${e.cover_image.url}" alt="[Coverpage]" />
|
||||
<p py:for="author in e.authors">${author.role}: ${author.name_and_dates}</p>
|
||||
<py:for each="marc in e.marcs">
|
||||
<py:choose test="">
|
||||
<p py:when="marc.code[0]=='5'">
|
||||
<?python
|
||||
text = gg.xmlspecialchars (marc.text)
|
||||
text = re.sub (r'(//\S+)', r'<a href="\1">\1</a>', text)
|
||||
text = re.sub (r'#(\d+)',
|
||||
r'<a href="/ebooks/\1.mobile">#\1</a>', text)
|
||||
?>
|
||||
${marc.caption}:
|
||||
${ Markup (gg.insert_breaks (text)) }
|
||||
</p>
|
||||
<p py:otherwise="">
|
||||
${marc.caption}:
|
||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
||||
</p>
|
||||
</py:choose>
|
||||
</py:for>
|
||||
<p>Ebook No.: ${e.project_gutenberg_id}</p>
|
||||
<p>Published: ${e.hr_release_date}</p>
|
||||
<p>Downloads: ${e.downloads}</p>
|
||||
<p py:for="language in e.languages">Language: ${language.language}</p>
|
||||
<p py:for="subject in e.subjects">Subject: ${subject.subject}</p>
|
||||
<p py:for="locc in e.loccs">LoCC: ${locc.locc}</p>
|
||||
<p py:for="category in e.categories">Category: ${category}</p>
|
||||
<p>Rights: ${e.rights}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</py:if>
|
||||
|
||||
<py:if test="isinstance (e, bs.Cat)">
|
||||
<py:choose test="">
|
||||
<py:when test="e.rel == '__statusline__'" />
|
||||
|
||||
<py:otherwise>
|
||||
<li class="${e.class_}">
|
||||
<a class="table link" href="${e.url}" accesskey="${str (n % 10)}">
|
||||
<span class="row">
|
||||
<span class="cell leftcell">
|
||||
<span class="icon icon_${e.icon}" />
|
||||
</span>
|
||||
<span class="cell content">
|
||||
<span py:if="e.title" class="title">${e.title}</span>
|
||||
<span py:if="e.subtitle" class="subtitle">${e.subtitle}</span>
|
||||
<span py:if="e.extra" class="extra">${e.extra}</span>
|
||||
</span>
|
||||
<span py:if="e.icon2" class="cell rightcell">
|
||||
<span class="icon icon_${e.icon2}" />
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</py:otherwise>
|
||||
</py:choose>
|
||||
</py:if>
|
||||
</py:for>
|
||||
|
||||
<py:if test="os.show_next_page_link">
|
||||
<li class="navlink more grayed">
|
||||
<a class="table link"
|
||||
href="${os.url_carry (start_index = os.next_page_index)}">
|
||||
<span class="row">
|
||||
<span class="cell leftcell">
|
||||
<span class="icon icon_more" />
|
||||
</span>
|
||||
<span class="cell content">
|
||||
<span class="title"><span>Next Page</span>…</span>
|
||||
</span>
|
||||
<span class="cell rightcell">
|
||||
<span class="icon spinner" />
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</py:if>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
${site_footer ()}
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -26,7 +26,6 @@
|
|||
<script>//<![CDATA[
|
||||
var json_search = "${os.json_search}";
|
||||
var canonical_url = "${os.canonical_url}";
|
||||
var mobile_url = "${os.canonical_url}";
|
||||
var lang = "${os.lang}";
|
||||
var fb_lang = "${os.fb_lang}"; /* FB accepts only xx_XX */
|
||||
var msg_load_more = "${_('Load More Results…')}";
|
||||
|
|
Loading…
Reference in New Issue