implemented ebook versions
It turned out that ebookfile handling needed revamping with the addition of ebook versions; so this change turned out to be rather big.pull/1/head
parent
651f45f624
commit
7ad0d7f494
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0004_auto_20160808_1548'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ebookfile',
|
||||
name='ebook',
|
||||
field=models.ForeignKey(related_name='ebook_files', to='core.Ebook', null=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from django.db import migrations, models
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
def add_ebooks_to_ebfs(apps, schema_editor):
|
||||
EbookFile = apps.get_model('core', 'EbookFile')
|
||||
Ebook = apps.get_model('core', 'Ebook')
|
||||
for ebf in EbookFile.objects.all():
|
||||
for ebook in Ebook.objects.filter(edition=ebf.edition, format=ebf.format).exclude(provider='Unglue.it'):
|
||||
ebf.ebook = ebook
|
||||
ebf.save()
|
||||
for ebook in Ebook.objects.filter(url=ebf.file.url):
|
||||
ebf.ebook = ebook
|
||||
ebf.save()
|
||||
if not ebf.ebook:
|
||||
if ebf.edition.work.campaigns.filter(type=3):
|
||||
ebf.ebook = Ebook.objects.create(
|
||||
edition=ebf.edition,
|
||||
active=False,
|
||||
url=ebf.file.url,
|
||||
provider='Unglue.it',
|
||||
format=ebf.format,
|
||||
rights=ebf.edition.work.campaigns.order_by('-created')[0].license
|
||||
)
|
||||
ebf.save()
|
||||
elif ebf.edition.work.campaigns.filter(type=2):
|
||||
pass
|
||||
else:
|
||||
print 'ebf {} is dangling'.format(ebf.id)
|
||||
|
||||
def noop(apps, schema_editor):
|
||||
pass
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_ebookfile_ebook'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_ebooks_to_ebfs, reverse_code=noop, hints={'core': 'EbookFile'}),
|
||||
]
|
|
@ -78,6 +78,7 @@ from .bibmodels import (
|
|||
EbookFile,
|
||||
Edition,
|
||||
EditionNote,
|
||||
good_providers,
|
||||
Identifier,
|
||||
path_for_file,
|
||||
Publisher,
|
||||
|
@ -675,7 +676,11 @@ class Campaign(models.Model):
|
|||
self.activated = datetime.today()
|
||||
if self.type == THANKS:
|
||||
# make ebooks from ebookfiles
|
||||
self.work.make_ebooks_from_ebfs()
|
||||
if self.use_add_ask:
|
||||
self.add_ask_to_ebfs()
|
||||
else:
|
||||
self.revert_asks()
|
||||
self.work.remove_old_ebooks()
|
||||
self.save()
|
||||
action = CampaignAction(campaign=self, type='activated', comment=self.get_type_display())
|
||||
ungluers = self.work.wished_by()
|
||||
|
@ -934,82 +939,112 @@ class Campaign(models.Model):
|
|||
def latest_ending(cls):
|
||||
return timedelta(days=int(settings.UNGLUEIT_LONGEST_DEADLINE)) + now()
|
||||
|
||||
def make_mobi(self):
|
||||
for ebf in self.work.ebookfiles().filter(format='epub').order_by('-created'):
|
||||
if ebf.active:
|
||||
new_mobi_ebf = EbookFile.objects.create(edition=ebf.edition, format='mobi', asking=ebf.asking)
|
||||
new_mobi_ebf.file.save(path_for_file('ebf', None), ContentFile(mobi.convert_to_mobi(ebf.file.url)))
|
||||
new_mobi_ebf.save()
|
||||
self.work.make_ebooks_from_ebfs()
|
||||
return True
|
||||
return False
|
||||
def make_mobis(self):
|
||||
# make archive files for ebooks, make mobi files for epubs
|
||||
versions = set()
|
||||
for ebook in self.work.ebooks().filter(provider__in=good_providers, format='mobi'):
|
||||
versions.add(ebook.version_label)
|
||||
for ebook in self.work.ebooks_all().exclude(provider='Unglue.it').filter(provider__in=good_providers, format='epub'):
|
||||
if not ebook.version_label in versions:
|
||||
# now make the mobi file
|
||||
ebf = ebook.get_archive_ebf()
|
||||
ebf.make_mobi()
|
||||
|
||||
def add_ask_to_ebfs(self, position=0):
|
||||
if not self.use_add_ask or self.type != THANKS:
|
||||
return
|
||||
pdf_to_do = pdf_edition = None
|
||||
epub_to_do = epub_edition = None
|
||||
new_ebfs = {}
|
||||
for ebf in self.work.ebookfiles().filter(asking=False).order_by('-created'):
|
||||
if ebf.format == 'pdf' and not pdf_to_do:
|
||||
format_versions = []
|
||||
to_dos = []
|
||||
for ebf in self.work.ebookfiles().filter(asking=False, ebook__provider='Unglue.it').order_by('-created'):
|
||||
format_version = '{}_{}'.format(ebf.ebook.format, ebf.ebook.version_label)
|
||||
if ebf.format in ('pdf', 'epub') and not format_version in format_versions:
|
||||
ebf.file.open()
|
||||
pdf_to_do = ebf.file.read()
|
||||
pdf_edition = ebf.edition
|
||||
elif ebf.format == 'epub' and not epub_to_do:
|
||||
ebf.file.open()
|
||||
epub_to_do = ebf.file.read()
|
||||
epub_edition = ebf.edition
|
||||
for ebook in self.work.ebooks_all().exclude(provider='Unglue.it'):
|
||||
if ebook.format == 'pdf' and not pdf_to_do:
|
||||
r = requests.get(ebook.url)
|
||||
pdf_to_do = r.content
|
||||
pdf_edition = ebook.edition
|
||||
elif ebook.format == 'epub' and not epub_to_do:
|
||||
r = requests.get(ebook.url)
|
||||
epub_to_do = r.content
|
||||
epub_edition = ebook.edition
|
||||
if pdf_to_do:
|
||||
try:
|
||||
added = ask_pdf({'campaign':self, 'work':self.work, 'site':Site.objects.get_current()})
|
||||
new_file = SpooledTemporaryFile()
|
||||
old_file = SpooledTemporaryFile()
|
||||
old_file.write(pdf_to_do)
|
||||
if position == 0:
|
||||
pdf_append(added, old_file, new_file)
|
||||
else:
|
||||
pdf_append(old_file, added, new_file)
|
||||
new_file.seek(0)
|
||||
new_pdf_ebf = EbookFile.objects.create(edition=pdf_edition, format='pdf', asking=True)
|
||||
new_pdf_ebf.file.save(path_for_file('ebf', None), ContentFile(new_file.read()))
|
||||
new_pdf_ebf.save()
|
||||
new_ebfs['pdf'] = new_pdf_ebf
|
||||
except Exception as e:
|
||||
logger.error("error appending pdf ask %s" % (e))
|
||||
if epub_to_do:
|
||||
try:
|
||||
old_file = SpooledTemporaryFile()
|
||||
old_file.write(epub_to_do)
|
||||
new_file = ask_epub(old_file, {'campaign':self, 'work':self.work, 'site':Site.objects.get_current()})
|
||||
new_file.seek(0)
|
||||
new_epub_ebf = EbookFile.objects.create(edition=epub_edition, format='epub', asking=True)
|
||||
new_epub_ebf.file.save(path_for_file(new_epub_ebf, None), ContentFile(new_file.read()))
|
||||
new_epub_ebf.save()
|
||||
new_ebfs['epub'] = new_epub_ebf
|
||||
# now make the mobi file
|
||||
new_mobi_ebf = EbookFile.objects.create(edition=epub_edition, format='mobi', asking=True)
|
||||
new_mobi_ebf.file.save(path_for_file('ebf', None), ContentFile(mobi.convert_to_mobi(new_epub_ebf.file.url)))
|
||||
new_mobi_ebf.save()
|
||||
new_ebfs['mobi'] = new_mobi_ebf
|
||||
except Exception as e:
|
||||
logger.error("error making epub ask or mobi %s" % (e))
|
||||
for key in new_ebfs.keys():
|
||||
for old_ebf in self.work.ebookfiles().filter(asking=True, format=key).exclude(pk=new_ebfs[key].pk):
|
||||
obsolete = Ebook.objects.filter(url=old_ebf.file.url)
|
||||
for eb in obsolete:
|
||||
eb.deactivate()
|
||||
old_ebf.file.delete()
|
||||
old_ebf.delete()
|
||||
self.work.make_ebooks_from_ebfs(add_ask=True)
|
||||
to_dos.append({'content': ebf.file.read(), 'ebook': ebf.ebook})
|
||||
format_versions.append(format_version)
|
||||
for ebook in self.work.ebooks_all().exclude(provider='Unglue.it').filter(provider__in=good_providers):
|
||||
format_version = '{}_{}'.format(ebook.format, ebook.version_label)
|
||||
if ebook.format in ('pdf', 'epub') and not format_version in format_versions:
|
||||
to_dos.append({'content': ebook.get_archive().read(), 'ebook': ebook})
|
||||
format_versions.append(format_version)
|
||||
new_ebfs = []
|
||||
for to_do in to_dos:
|
||||
edition = to_do['ebook'].edition
|
||||
version = to_do['ebook'].version
|
||||
if to_do['ebook'].format == 'pdf':
|
||||
try:
|
||||
added = ask_pdf({'campaign':self, 'work':self.work, 'site':Site.objects.get_current()})
|
||||
new_file = SpooledTemporaryFile()
|
||||
old_file = SpooledTemporaryFile()
|
||||
old_file.write(to_do['content'])
|
||||
if position == 0:
|
||||
pdf_append(added, old_file, new_file)
|
||||
else:
|
||||
pdf_append(old_file, added, new_file)
|
||||
new_file.seek(0)
|
||||
new_pdf_ebf = EbookFile.objects.create(edition=edition, format='pdf', asking=True)
|
||||
new_pdf_ebf.version = version
|
||||
new_pdf_ebf.file.save(path_for_file('ebf', None), ContentFile(new_file.read()))
|
||||
new_pdf_ebf.save()
|
||||
new_ebfs.append(new_pdf_ebf)
|
||||
except Exception as e:
|
||||
logger.error("error appending pdf ask %s" % (e))
|
||||
elif to_do['ebook'].format == 'epub':
|
||||
try:
|
||||
old_file = SpooledTemporaryFile()
|
||||
old_file.write(to_do['content'])
|
||||
new_file = ask_epub(old_file, {'campaign':self, 'work':self.work, 'site':Site.objects.get_current()})
|
||||
new_file.seek(0)
|
||||
new_epub_ebf = EbookFile.objects.create(edition=edition, format='epub', asking=True)
|
||||
new_epub_ebf.file.save(path_for_file(new_epub_ebf, None), ContentFile(new_file.read()))
|
||||
new_epub_ebf.save()
|
||||
new_epub_ebf.version = version
|
||||
new_ebfs.append(new_epub_ebf)
|
||||
|
||||
# now make the mobi file
|
||||
new_mobi_ebf = EbookFile.objects.create(edition=edition, format='mobi', asking=True)
|
||||
new_mobi_ebf.file.save(path_for_file('ebf', None), ContentFile(mobi.convert_to_mobi(new_epub_ebf.file.url)))
|
||||
new_mobi_ebf.save()
|
||||
new_mobi_ebf.version = version
|
||||
new_ebfs.append(new_mobi_ebf)
|
||||
except Exception as e:
|
||||
logger.error("error making epub ask or mobi %s" % (e))
|
||||
for ebf in new_ebfs:
|
||||
ebook = Ebook.objects.create(
|
||||
edition=ebf.edition,
|
||||
format=ebf.format,
|
||||
rights=self.license,
|
||||
provider="Unglue.it",
|
||||
url=ebf.file.url,
|
||||
version=ebf.version
|
||||
)
|
||||
ebf.ebook = ebook
|
||||
ebf.save()
|
||||
new_ebf_pks = [ebf.pk for ebf in new_ebfs]
|
||||
|
||||
for old_ebf in self.work.ebookfiles().filter(asking=True).exclude(pk__in=new_ebf_pks):
|
||||
obsolete = Ebook.objects.filter(url=old_ebf.file.url)
|
||||
old_ebf.ebook.deactivate()
|
||||
old_ebf.file.delete()
|
||||
old_ebf.delete()
|
||||
|
||||
for non_asking in self.work.ebookfiles().filter(asking=False, ebook__active=True):
|
||||
non_asking.ebook.deactivate()
|
||||
|
||||
def revert_asks(self):
|
||||
# there should be a deactivated non-asking ebook for every asking ebook
|
||||
if self.type != THANKS: # just to make sure that ebf's can be unglued by mistake
|
||||
return
|
||||
format_versions = []
|
||||
for ebf in EbookFile.objects.filter(edition__work=self.work).exclude(file='').exclude(ebook=None).order_by('-created'):
|
||||
format_version = '{}_{}'.format(ebf.format, ebf.ebook.version_label)
|
||||
if ebf.asking:
|
||||
ebf.ebook.deactivate()
|
||||
elif format_version in format_versions:
|
||||
# this ebook file has the wrong "asking"
|
||||
ebf.ebook.deactivate()
|
||||
else:
|
||||
ebf.ebook.activate()
|
||||
format_versions.append(format_version)
|
||||
|
||||
def make_unglued_ebf(self, format, watermarked):
|
||||
r = urllib2.urlopen(watermarked.download_link(format))
|
||||
|
@ -1023,6 +1058,7 @@ class Campaign(models.Model):
|
|||
rights=self.license,
|
||||
provider="Unglue.it",
|
||||
url=settings.BASE_URL_SECURE + reverse('download_campaign', args=[self.work.id, format]),
|
||||
version='unglued',
|
||||
)
|
||||
old_ebooks = Ebook.objects.exclude(pk=ebook.pk).filter(
|
||||
edition=self.work.preferred_edition,
|
||||
|
|
|
@ -25,8 +25,10 @@ from regluit.marc.models import MARCRecord as NewMARC
|
|||
from regluit.utils.localdatetime import now
|
||||
from regluit.questionnaire.models import Landing
|
||||
|
||||
from regluit.core import mobi
|
||||
import regluit.core.cc as cc
|
||||
from regluit.core.epub import test_epub
|
||||
|
||||
from regluit.core.parameters import (
|
||||
AGE_LEVEL_CHOICES,
|
||||
BORROWED,
|
||||
|
@ -41,6 +43,7 @@ from regluit.core.parameters import (
|
|||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
good_providers = ('Internet Archive', 'Unglue.it', 'Github', 'OAPEN Library')
|
||||
|
||||
|
||||
class Identifier(models.Model):
|
||||
|
@ -360,7 +363,15 @@ class Work(models.Model):
|
|||
|
||||
def pdffiles(self):
|
||||
return EbookFile.objects.filter(edition__work=self, format='pdf').exclude(file='').order_by('-created')
|
||||
|
||||
|
||||
def versions(self):
|
||||
version_labels = ['']
|
||||
for ebook in self.ebooks():
|
||||
if not ebook.version_label in version_labels:
|
||||
version_labels.append(ebook.version_label)
|
||||
version_labels.remove('')
|
||||
return version_labels
|
||||
|
||||
def formats(self):
|
||||
fmts = []
|
||||
for fmt in ['pdf', 'epub', 'mobi', 'html']:
|
||||
|
@ -369,48 +380,20 @@ class Work(models.Model):
|
|||
break
|
||||
return fmts
|
||||
|
||||
def make_ebooks_from_ebfs(self, add_ask=True):
|
||||
# either the ebf has been uploaded or a created (perhaps an ask was added or mobi generated)
|
||||
if self.last_campaign().type != THANKS: # just to make sure that ebf's can be unglued by mistake
|
||||
return
|
||||
ebfs = EbookFile.objects.filter(edition__work=self).exclude(file='').order_by('-created')
|
||||
done_formats = []
|
||||
for ebf in ebfs:
|
||||
previous_ebooks = Ebook.objects.filter(url=ebf.file.url,)
|
||||
try:
|
||||
previous_ebook = previous_ebooks[0]
|
||||
for eb in previous_ebooks[1:]: #housekeeping
|
||||
eb.deactivate()
|
||||
except IndexError:
|
||||
previous_ebook = None
|
||||
|
||||
if ebf.format not in done_formats:
|
||||
if ebf.asking == add_ask or ebf.format == 'mobi':
|
||||
if previous_ebook:
|
||||
previous_ebook.activate()
|
||||
else:
|
||||
ebook = Ebook.objects.get_or_create(
|
||||
edition=ebf.edition,
|
||||
format=ebf.format,
|
||||
rights=self.last_campaign().license,
|
||||
provider="Unglue.it",
|
||||
url=ebf.file.url,
|
||||
)
|
||||
done_formats.append(ebf.format)
|
||||
elif previous_ebook:
|
||||
previous_ebook.deactivate()
|
||||
elif previous_ebook:
|
||||
previous_ebook.deactivate()
|
||||
return
|
||||
|
||||
def remove_old_ebooks(self):
|
||||
# this method is triggered after an file upload or new ebook saved
|
||||
old = Ebook.objects.filter(edition__work=self, active=True).order_by('-created')
|
||||
done_formats = []
|
||||
|
||||
# keep most recent ebook for each format and version label
|
||||
done_format_versions = []
|
||||
for eb in old:
|
||||
if eb.format in done_formats:
|
||||
format_version = '{}_{}'.format(eb.format, eb.version_label)
|
||||
if format_version in done_format_versions:
|
||||
eb.deactivate()
|
||||
else:
|
||||
done_formats.append(eb.format)
|
||||
done_format_versions.append(format_version)
|
||||
|
||||
# check for failed uploads.
|
||||
null_files = EbookFile.objects.filter(edition__work=self, file='')
|
||||
for ebf in null_files:
|
||||
ebf.file.delete()
|
||||
|
@ -1005,7 +988,8 @@ class EbookFile(models.Model):
|
|||
edition = models.ForeignKey('Edition', related_name='ebook_files')
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
asking = models.BooleanField(default=False)
|
||||
|
||||
ebook = models.ForeignKey('Ebook', related_name='ebook_files', null=True)
|
||||
version = None
|
||||
def check_file(self):
|
||||
if self.format == 'epub':
|
||||
return test_epub(self.file)
|
||||
|
@ -1018,6 +1002,24 @@ class EbookFile(models.Model):
|
|||
except:
|
||||
return False
|
||||
|
||||
def make_mobi(self):
|
||||
if not self.format == 'epub':
|
||||
return False
|
||||
new_mobi_ebf = EbookFile.objects.create(edition=self.edition, format='mobi', asking=self.asking)
|
||||
new_mobi_ebf.file.save(path_for_file('ebf', None), ContentFile(mobi.convert_to_mobi(self.file.url)))
|
||||
new_mobi_ebf.save()
|
||||
if self.ebook:
|
||||
new_ebook = Ebook.objects.create(
|
||||
edition=self.edition,
|
||||
format='mobi',
|
||||
url=new_mobi_ebf.file.url,
|
||||
rights=self.ebook.rights,
|
||||
version=self.ebook.version,
|
||||
)
|
||||
new_mobi_ebf.ebook = new_ebook
|
||||
new_mobi_ebf.save()
|
||||
return True
|
||||
|
||||
send_to_kindle_limit = 7492232
|
||||
|
||||
class Ebook(models.Model):
|
||||
|
@ -1041,49 +1043,63 @@ class Ebook(models.Model):
|
|||
else:
|
||||
return False
|
||||
|
||||
def get_archive(self): # returns an archived file
|
||||
if self.edition.ebook_files.filter(format=self.format).count() == 0:
|
||||
if self.provider is not 'Unglue.it':
|
||||
try:
|
||||
r = urllib2.urlopen(self.url)
|
||||
try:
|
||||
self.filesize = int(r.info().getheaders("Content-Length")[0])
|
||||
if self.save:
|
||||
self.filesize = self.filesize if self.filesize < 2147483647 else 2147483647 # largest safe positive integer
|
||||
self.save()
|
||||
ebf = EbookFile.objects.create(edition=self.edition, format=self.format)
|
||||
ebf.file.save(path_for_file(ebf, None), ContentFile(r.read()))
|
||||
ebf.file.close()
|
||||
ebf.save()
|
||||
ebf.file.open()
|
||||
return ebf.file
|
||||
except IndexError:
|
||||
# response has no Content-Length header probably a bad link
|
||||
logging.error('Bad link error: {}'.format(self.url))
|
||||
except IOError:
|
||||
logger.error(u'could not open {}'.format(self.url))
|
||||
else:
|
||||
# this shouldn't happen, except in testing perhaps
|
||||
logger.error(u'couldn\'t find ebookfile for {}'.format(self.url))
|
||||
# try the url instead
|
||||
f = urllib.urlopen(self.url)
|
||||
return f
|
||||
else:
|
||||
ebf = self.edition.ebook_files.filter(format=self.format).order_by('-created')[0]
|
||||
def get_archive(self): # returns an open file
|
||||
ebf = self.get_archive_ebf()
|
||||
if not ebf:
|
||||
return None
|
||||
try:
|
||||
ebf.file.open()
|
||||
except ValueError:
|
||||
logger.error(u'couldn\'t open EbookFile {}'.format(ebf.id))
|
||||
return None
|
||||
except IOError:
|
||||
logger.error(u'EbookFile {} does not exist'.format(ebf.id))
|
||||
return None
|
||||
return ebf.file
|
||||
|
||||
def get_archive_ebf(self): # returns an ebf
|
||||
if not self.ebook_files.filter(asking=False):
|
||||
if not self.provider in good_providers:
|
||||
return None
|
||||
try:
|
||||
ebf.file.open()
|
||||
except ValueError:
|
||||
logger.error(u'couldn\'t open EbookFile {}'.format(ebf.id))
|
||||
return None
|
||||
r = urllib2.urlopen(self.url)
|
||||
try:
|
||||
self.filesize = int(r.info().getheaders("Content-Length")[0])
|
||||
if self.save:
|
||||
self.filesize = self.filesize if self.filesize < 2147483647 else 2147483647 # largest safe positive integer
|
||||
self.save()
|
||||
ebf = EbookFile.objects.create(edition=self.edition, ebook=self, format=self.format)
|
||||
ebf.file.save(path_for_file(ebf, None), ContentFile(r.read()))
|
||||
ebf.file.close()
|
||||
ebf.save()
|
||||
return ebf
|
||||
except IndexError:
|
||||
# response has no Content-Length header probably a bad link
|
||||
logging.error('Bad link error: {}'.format(self.url))
|
||||
except IOError:
|
||||
logger.error(u'EbookFile {} does not exist'.format(ebf.id))
|
||||
return None
|
||||
return ebf.file
|
||||
logger.error(u'could not open {}'.format(self.url))
|
||||
else:
|
||||
ebf = self.ebook_files.filter(asking=False).order_by('-created')[0]
|
||||
return ebf
|
||||
|
||||
def set_provider(self):
|
||||
self.provider = Ebook.infer_provider(self.url)
|
||||
return self.provider
|
||||
|
||||
@property
|
||||
def version_label(self):
|
||||
if self.version is None:
|
||||
return ''
|
||||
version_match = re.search(r'(.*)\.(\d+)$',self.version)
|
||||
return version_match.group(1) if version_match else self.version
|
||||
|
||||
@property
|
||||
def version_iter(self):
|
||||
if self.version is None:
|
||||
return 0
|
||||
version_match = re.search(r'(.*)\.(\d+)$',self.version)
|
||||
return int(version_match.group(2)) if version_match else 0
|
||||
|
||||
@property
|
||||
def rights_badge(self):
|
||||
if self.rights is None:
|
||||
|
|
|
@ -134,12 +134,13 @@ def process_ebfs(campaign):
|
|||
if campaign.use_add_ask:
|
||||
campaign.add_ask_to_ebfs()
|
||||
else:
|
||||
campaign.work.make_ebooks_from_ebfs(add_ask=False)
|
||||
campaign.work.remove_old_ebooks()
|
||||
campaign.revert_asks()
|
||||
campaign.make_mobis()
|
||||
|
||||
|
||||
@task
|
||||
def make_mobi(campaign):
|
||||
return campaign.make_mobi()
|
||||
def make_mobi(ebookfile):
|
||||
return ebookfile.make_mobi()
|
||||
|
||||
@task
|
||||
def refresh_acqs():
|
||||
|
|
|
@ -1011,6 +1011,11 @@ class EbookFileTests(TestCase):
|
|||
dj_file = DjangoFile(temp_file)
|
||||
ebf = EbookFile( format='pdf', edition=e, file=dj_file)
|
||||
ebf.save()
|
||||
eb = Ebook( format='pdf', edition=e, url=ebf.file.url, provider='Unglue.it')
|
||||
eb.save()
|
||||
ebf.ebook = eb
|
||||
ebf.save()
|
||||
|
||||
|
||||
temp_file.close()
|
||||
finally:
|
||||
|
@ -1018,7 +1023,7 @@ class EbookFileTests(TestCase):
|
|||
os.remove(temp.name)
|
||||
#test the ask-appender
|
||||
c.add_ask_to_ebfs()
|
||||
asking_pdf = c.work.ebookfiles().filter(asking = True)[0].file.url
|
||||
asking_pdf = c.work.ebookfiles().filter(asking=True)[0].file.url
|
||||
assert test_pdf(asking_pdf)
|
||||
|
||||
#Now do the same with epub
|
||||
|
@ -1034,16 +1039,25 @@ class EbookFileTests(TestCase):
|
|||
dj_file = DjangoFile(temp_file)
|
||||
ebf = EbookFile( format='epub', edition=e, file=dj_file)
|
||||
ebf.save()
|
||||
|
||||
eb = Ebook( format='epub', edition=e, url=ebf.file.url, provider='Unglue.it')
|
||||
eb.save()
|
||||
ebf.ebook = eb
|
||||
ebf.save()
|
||||
temp_file.close()
|
||||
ebf.make_mobi()
|
||||
finally:
|
||||
# make sure we get rid of temp file
|
||||
os.remove(temp.name)
|
||||
#test the ask-appender
|
||||
c.add_ask_to_ebfs()
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, format='epub').count >0)
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, format='mobi').count >0)
|
||||
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, format='epub').count() > 0)
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, format='mobi').count() > 0)
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, ebook__active=True).count() > 0)
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = False, ebook__active=True).count() == 0)
|
||||
#test the unasker
|
||||
c.revert_asks()
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = True, ebook__active=True).count() == 0)
|
||||
self.assertTrue( c.work.ebookfiles().filter(asking = False, ebook__active=True).count() > 0)
|
||||
|
||||
class MobigenTests(TestCase):
|
||||
def test_convert_to_mobi(self):
|
||||
|
|
|
@ -4,7 +4,7 @@ from StringIO import StringIO
|
|||
|
||||
|
||||
from regluit.core.facets import BaseFacet
|
||||
from regluit.core.models import Work
|
||||
from regluit.core.models import Work, good_providers
|
||||
from regluit.api.onix import onix_feed
|
||||
|
||||
from .models import Target
|
||||
|
@ -45,7 +45,7 @@ def get_target_facet(target, start=datetime(1900,1,1), new=False):
|
|||
editions__ebooks__created__gt = start,
|
||||
identifiers__type="isbn",
|
||||
editions__ebooks__format__in = formats,
|
||||
editions__ebooks__provider__in = ('Internet Archive', 'Unglue.it', 'Github', 'OAPEN Library'),
|
||||
editions__ebooks__provider__in = good_providers,
|
||||
).distinct().order_by('-featured')
|
||||
|
||||
model_filters = {"Ebook": format_filter, "Edition": edition_format_filter}
|
||||
|
|
|
@ -261,7 +261,8 @@ class EditionForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
class EbookFileForm(forms.ModelForm):
|
||||
file = forms.FileField(max_length=16777216)
|
||||
version = forms.CharField(max_length=512, required=False)
|
||||
file = forms.FileField(max_length=16777216)
|
||||
|
||||
def __init__(self, campaign_type=BUY2UNGLUE, *args, **kwargs):
|
||||
super(EbookFileForm, self).__init__(*args, **kwargs)
|
||||
|
@ -305,7 +306,7 @@ class EbookFileForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = EbookFile
|
||||
widgets = { 'edition': forms.HiddenInput}
|
||||
exclude = { 'created', 'asking' }
|
||||
exclude = { 'created', 'asking', 'ebook' }
|
||||
|
||||
class EbookForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
|
|
@ -149,7 +149,7 @@ $j(document).ready(function() {
|
|||
<a href="{% url 'download_ebook' ebook.id %}">
|
||||
<img src="{{ ebook.rights_badge }}" alt="{{ ebook.rights}}" title="{{ ebook.rights}}" /></a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}"><img src="/static/images/{{ ebook.format }}32.png" height="32" alt="{{ ebook.format }}" title="{{ ebook.format }}" /></a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }}</a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }}</a> {% if ebook.version_label %} ({{ ebook.version_label }}) {% endif %}
|
||||
{% if ebook.is_direct %}<a class="dropbox-saver" href="{{ ebook.download_url }}" data-filename="unglueit-{{ work.id }}.{{ ebook.format }}"></a>{% endif %}
|
||||
|
||||
|
||||
|
@ -168,7 +168,7 @@ $j(document).ready(function() {
|
|||
<a href="{% url 'download_ebook' ebook.id %}">
|
||||
<img src="{{ ebook.rights_badge }}" alt="{{ ebook.rights}}" title="{{ ebook.rights}}" /></a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}"><img src="/static/images/{{ ebook.format }}32.png" height="32" alt="{{ ebook.format }} at {{ebook.provider}}" title="{{ ebook.format }} at {{ebook.provider}}" /></a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }} at {{ ebook.provider }}</a>
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }} {% if ebook.version_label %} ({{ ebook.version_label }}) {% endif %} at {{ ebook.provider }}</a>
|
||||
{% if ebook.is_direct %}<a class="dropbox-saver" href="{{ ebook.download_url }}" data-filename="unglueit-{{ work.id }}.{{ ebook.format }}"></a>{% endif %}
|
||||
|
||||
{% if not forloop.last %}<br /><br />{% endif %}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
{% if edition.note %}
|
||||
{{ edition.note }}.<br />
|
||||
{% endif %}
|
||||
{% if edition.ebooks.all %}
|
||||
{{ edition.ebooks.all.count }} ebooks<br />
|
||||
{% if edition.downloads.count %}
|
||||
{{ edition.downloads.count }} ebooks<br />
|
||||
{% endif %}
|
||||
{% if edition.publisher %}
|
||||
Publisher: <a href="{% url 'bypubname_list' edition.publisher_name.id %}">{{edition.publisher}}</a><br />
|
||||
|
|
|
@ -7,21 +7,32 @@
|
|||
<h2>eBooks for this Edition</h2>
|
||||
|
||||
{% for ebook in edition.ebooks.all %}
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }}</a> {{ebook.rights}} at {{ebook.provider}}. Downloaded {{ ebook.download_count }} times.<br />
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }}</a> {{ebook.rights}} at {{ebook.provider}}.
|
||||
{% if ebook.version %} {{ ebook.version }}. {% endif %}
|
||||
Downloaded {{ ebook.download_count }} times since {{ ebook.created }}<br />
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<h2>Add an eBook for this Edition:</h2>
|
||||
|
||||
<span>If you know that this edition is available as a public domain or Creative Commons ebook, you can enter the link here and "unglue" it. Right now, we're only accepting URLs that point to Internet Archive, Wikisources, Wikibooks, Hathitrust, Project Gutenberg, raw files at Github, or Google Books.</span>
|
||||
<span>If you know that this edition is available as a public domain or Creative Commons ebook, you can enter the link here and "unglue" it. Right now, we're only accepting URLs that point to Internet Archive, Wikisources, Wikibooks, Hathitrust, Project Gutenberg, OApen, raw files at Github, or Google Books.</span>
|
||||
|
||||
<form method="POST" action="#add_ebook">
|
||||
{% csrf_token %}{{ edition.ebook_form.edition.errors }}{{ edition.ebook_form.edition }}{{ edition.ebook_form.user.errors }}{{ edition.ebook_form.user }}{{ edition.ebook_form.provider.errors }}{{ edition.ebook_form.provider }}
|
||||
{{ edition.ebook_form.url.errors }}<span>URL: {{ edition.ebook_form.url }}</span><br />
|
||||
{{ edition.ebook_form.format.errors }}<span>File Format: {{ edition.ebook_form.format }}</span>
|
||||
{{ edition.ebook_form.rights.errors }}<span>License: {{ edition.ebook_form.rights }}</span><br />
|
||||
{{ edition.ebook_form.version.errors }}<span>Version: {{ edition.ebook_form.version }} </span><br />
|
||||
<input type="submit" name="add_ebook" value="add ebook" />
|
||||
</form>
|
||||
<h3>Note on versions</h4>
|
||||
<p>
|
||||
Unglue.it's version strings have two components, a label and a iteration.
|
||||
The iteration is denoted by a dot and a number at the end of version string, and is assumed to be 0 if not given explicitly.
|
||||
Unglue.it will show the user just the label and will suppress display of all but the highest iteration for a given label.
|
||||
so if the ebooks have versions "", ".1", "1.0.0", "1.0.2", "Open Access" and "Open Access.1", Unglue.it will display 3 ebooks labelled "", "1.0" and "Open Access".
|
||||
If you want ebooks from two editions with the same format to display, give them different version labels.
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div> Adding ebook links is disabled for this work.</div>
|
||||
|
|
|
@ -20,12 +20,20 @@
|
|||
<b>LibraryThing ID</b>: {{ edition.librarything_id }}<br />
|
||||
|
||||
</div>
|
||||
{% if edition.ebooks.all.0 %}
|
||||
<h2>Active eBooks for this Work</h2>
|
||||
{% for ebook in edition.work.ebooks %}
|
||||
<a href="{% url 'download_ebook' ebook.id %}">{{ ebook.format }}</a> {{ebook.rights}} at {{ebook.provider}}.
|
||||
{% if ebook.version %} {{ ebook.version }}. {% endif %}
|
||||
Downloaded {{ ebook.download_count }} times since {{ ebook.created }}<br />
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if edition.ebook_files.all %}
|
||||
<h2> Ebook Files for this Edition</h2>
|
||||
<ul>
|
||||
{% for ebook_file in edition.ebook_files.all %}
|
||||
{% if ebook_file.file %}
|
||||
<li>{% if ebook_file.active %}<span class="yikes">ACTIVE</span> {% endif %}<a href="{{ebook_file.file.url}}">{{ebook_file.file}}</a> created {{ebook_file.created}} {% if ebook_file.asking %}(This file has had the campaign 'ask' added.){% endif %}</li>
|
||||
<li>{% if ebook_file.active %}<span class="yikes">ACTIVE</span> {% elif ebook_file.ebook.active %} MIRROR {% endif %}<a href="{{ebook_file.file.url}}">{{ebook_file.file}}</a> created {{ebook_file.created}} {% if ebook_file.asking %}(This file has had the campaign 'ask' added.){% endif %}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -66,15 +74,27 @@
|
|||
For ePUB files, use the <a href=https://code.google.com/p/epubcheck/">epubcheck</a> tool to make sure everything will work properly.</p>
|
||||
<form method="POST" action="#" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{form.as_p}}
|
||||
{{form.edition.errors}}{{form.edition}}
|
||||
<p>{{form.format.errors}}Format: {{form.format}}</p>
|
||||
{% if edition.work.versions %}
|
||||
<p>There are named versions for this ebook. Specify the version you want to replace.<br /> {{form.version.errors}}Version: <select id="version">
|
||||
<option value="{{ version }}" >---</option>
|
||||
{% for version in edition.work.versions %}
|
||||
<option value="{{ version }}" >{{ version }}</option>
|
||||
{% endfor %}
|
||||
</select></p>
|
||||
{% else %}
|
||||
<input type="hidden" value="" id="version" name="version"/>
|
||||
{% endif %}
|
||||
<p>{{form.file.errors}}Upload File: {{form.file}}</p>
|
||||
<input type="submit" id="submit_file" value="submit ebook file">
|
||||
</form>
|
||||
{% if edition.work %}
|
||||
|
||||
<h2>More Edition Management</h2>
|
||||
|
||||
<div><a href="{% url 'new_edition' edition.work.id edition.id %}">Edit this edition</a></div>
|
||||
{% if edition.work.last_campaign %}
|
||||
<div><a href="{% url 'manage_campaign' edition.work.last_campaign.id %}">Manage this campaign</a></div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -136,14 +136,13 @@ Please fix the following before launching your campaign:
|
|||
<div class="edition_form" id="edition_{{edition.id}}">
|
||||
<p> Edition {{ edition.id }}: <input type="radio" {% ifequal edition.id form.edition.value %}checked="checked" {% endifequal %}id="id_edition_{{forloop.counter}}" value="{{edition.id}}" name="edition" /><label for="id_edition_{{forloop.counter}}"> Prefer this edition </label>
|
||||
<ul style="text-indent:1em">
|
||||
<li style="text-indent:2.5em">There are {{ edition.downloads.all.count }} downloadable ebook for this edition</li>
|
||||
<li style="text-indent:2.5em"><a href="{% url 'new_edition' edition.work.id edition.id %}"> Edit </a> this edition</li>
|
||||
{% ifnotequal campaign.type 1 %}
|
||||
{% if campaign.rh.can_sell %}
|
||||
{% if edition.ebook_files.all.0 %}
|
||||
<li style="text-indent:2.5em">You have uploaded ebook files for this edition. <a href="{% url 'edition_uploads' edition.id %}"> Upload another</a></li>
|
||||
<li style="text-indent:2.5em">You have uploaded ebook files for this edition. You can <a href="{% url 'edition_uploads' edition.id %}"> manage its ebooks or upload another</a></li>
|
||||
{% else %}
|
||||
<li style="text-indent:2.5em">You can <a href="{% url 'edition_uploads' edition.id %}"> Load a file</a> for this edition.</li>
|
||||
<li style="text-indent:2.5em">You can <a href="{% url 'edition_uploads' edition.id %}"> Manage ebooks</a> for this edition.</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endifnotequal %}
|
||||
|
@ -156,11 +155,11 @@ Please fix the following before launching your campaign:
|
|||
|
||||
<p>If you don't see an edition that matches what you want to release, you can <a href="{% url 'rh_edition' work.id '' %}">create a new edition</a>.</p>
|
||||
{% if campaign.work.ebookfiles.0 %}
|
||||
<h3>Uploaded Files</h3>
|
||||
<h3>All ebook files for this book</h3>
|
||||
{% endif %}
|
||||
{% if campaign.work.epubfiles.0 %}
|
||||
{% for ebf in campaign.work.epubfiles %}
|
||||
<p>{% if ebf.active %}<span class="yikes">ACTIVE</span> {% endif %}EPUB file: <a href="{{ebf.file.url}}">{{ebf.file}}</a> <br />created {{ebf.created}} for edition <a href="#edition_{{ebf.edition.id}}">{{ebf.edition.id}}</a> {% if ebf.asking %}(This file has had the campaign 'ask' added.){% endif %}<br />{% if ebf.active %}{% ifequal action 'mademobi' %}<span class="yikes">A MOBI file is being generated. </span> (Takes a minute or two.) {% else %}You can <a href="{% url 'makemobi' campaign.id %}">generate a MOBI file.</a> {% endifequal %}{% endif %}</p>
|
||||
<p>{% if ebf.active %}<span class="yikes">ACTIVE</span> {% elif ebf.ebook.active %} MIRROR {% endif %}EPUB file: <a href="{{ebf.file.url}}">{{ebf.file}}</a> <br />created {{ebf.created}} for edition <a href="#edition_{{ebf.edition.id}}">{{ebf.edition.id}}</a> {% if ebf.asking %}(This file has had the campaign 'ask' added.){% endif %}<br />{% if ebf.active %}{% ifequal action 'mademobi' %}<span class="yikes">A MOBI file is being generated. </span> (Takes a minute or two.) {% else %}You can <a href="{% url 'makemobi' campaign.id ebf.id %}">generate a MOBI file.</a> {% endifequal %}{% endif %}</p>
|
||||
{% endfor %}
|
||||
{% if campaign.work.test_acqs.0 %}
|
||||
<ul>
|
||||
|
|
|
@ -431,7 +431,7 @@
|
|||
This work has been downloaded {{ work.download_count }} times via unglue.it ebook links.
|
||||
<ol>
|
||||
{% for ebook in work.ebooks.all %}
|
||||
<li>{{ ebook.download_count }} - {{ ebook.format }} ({{ ebook.rights }}) at {{ ebook.provider }}</li>
|
||||
<li>{{ ebook.download_count }} - {{ ebook.format }} {% if ebook.version %} {{ ebook.version }} {% endif %}({{ ebook.rights }}) at {{ ebook.provider }}. </li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
|
|
|
@ -27,7 +27,7 @@ urlpatterns = [
|
|||
url(r"^rightsholders/$", views.rh_tools, name="rightsholders"),
|
||||
url(r"^rightsholders/campaign/(?P<id>\d+)/$", views.manage_campaign, name="manage_campaign"),
|
||||
url(r"^rightsholders/campaign/(?P<id>\d+)/results/$", views.manage_campaign, {'action': 'results'}, name="campaign_results"),
|
||||
url(r"^rightsholders/campaign/(?P<id>\d+)/makemobi/$", views.manage_campaign, {'action': 'makemobi'}, name="makemobi"),
|
||||
url(r"^rightsholders/campaign/(?P<id>\d+)/(?P<ebf>\d+)/makemobi/$", views.manage_campaign, {'action': 'makemobi'}, name="makemobi"),
|
||||
url(r"^rightsholders/campaign/(?P<id>\d+)/mademobi/$", views.manage_campaign, {'action': 'mademobi'}, name="mademobi"),
|
||||
url(r"^rightsholders/edition/(?P<work_id>\d*)/(?P<edition_id>\d*)$", views.new_edition, {'by': 'rh'}, name="rh_edition"),
|
||||
url(r"^rightsholders/edition/(?P<edition_id>\d*)/upload/$", views.edition_uploads, name="edition_uploads"),
|
||||
|
|
|
@ -428,9 +428,8 @@ def edition_uploads(request, edition_id):
|
|||
except models.Edition.DoesNotExist:
|
||||
raise Http404
|
||||
campaign_type = edition.work.last_campaign().type
|
||||
if not request.user.is_staff :
|
||||
if not request.user in edition.work.last_campaign().managers.all():
|
||||
return render(request, "admins_only.html")
|
||||
if not user_can_edit_work(request.user, edition.work):
|
||||
return render(request, "admins_only.html")
|
||||
if request.method == 'POST' :
|
||||
form = EbookFileForm(data=request.POST, files=request.FILES, campaign_type=campaign_type)
|
||||
if form.is_valid() :
|
||||
|
@ -462,6 +461,19 @@ def edition_uploads(request, edition_id):
|
|||
form.instance.delete()
|
||||
else:
|
||||
tasks.process_ebfs.delay(edition.work.last_campaign())
|
||||
if form.instance.id:
|
||||
new_ebook = models.Ebook.objects.create(
|
||||
edition=edition,
|
||||
format=form.instance.format,
|
||||
url=form.instance.file.url,
|
||||
rights=edition.work.last_campaign().license,
|
||||
version=form.cleaned_data['version'],
|
||||
active=False,
|
||||
provider="Unglue.it",
|
||||
)
|
||||
form.instance.ebook = new_ebook
|
||||
form.instance.save()
|
||||
|
||||
else:
|
||||
context['upload_error'] = form.errors
|
||||
form = EbookFileForm(initial={'edition':edition, 'format':'epub'}, campaign_type=campaign_type)
|
||||
|
@ -654,19 +666,10 @@ def manage_ebooks(request, edition_id, by=None):
|
|||
work = edition.work
|
||||
else:
|
||||
raise Http404
|
||||
if not request.user.is_authenticated() :
|
||||
return render(request, "admins_only.html")
|
||||
# if the work and edition are set, we save the edition and set the work
|
||||
|
||||
alert = ''
|
||||
admin = False
|
||||
if request.user.is_staff :
|
||||
admin = True
|
||||
elif work and work.last_campaign():
|
||||
if request.user in work.last_campaign().managers.all():
|
||||
admin = True
|
||||
elif work == None and request.user.rights_holder.count():
|
||||
admin = True
|
||||
admin = user_can_edit_work(request.user, work)
|
||||
if request.method == 'POST' :
|
||||
edition.new_authors = zip(request.POST.getlist('new_author'), request.POST.getlist('new_author_relation'))
|
||||
edition.new_subjects = request.POST.getlist('new_subject')
|
||||
|
@ -680,6 +683,7 @@ def manage_ebooks(request, edition_id, by=None):
|
|||
edition.ebook_form = EbookForm(data = request.POST, prefix = 'ebook_%d'%edition.id)
|
||||
if edition.ebook_form.is_valid():
|
||||
edition.ebook_form.save()
|
||||
edition.work.remove_old_ebooks()
|
||||
alert = 'Thanks for adding an ebook to unglue.it!'
|
||||
else:
|
||||
alert = 'your submitted ebook had errors'
|
||||
|
@ -700,7 +704,7 @@ def campaign_results(request, campaign):
|
|||
})
|
||||
|
||||
|
||||
def manage_campaign(request, id, action='manage'):
|
||||
def manage_campaign(request, id, ebf=None, action='manage'):
|
||||
campaign = get_object_or_404(models.Campaign, id=id)
|
||||
campaign.not_manager = False
|
||||
campaign.problems = []
|
||||
|
@ -782,7 +786,8 @@ def manage_campaign(request, id, action='manage'):
|
|||
activetab = '#2'
|
||||
else:
|
||||
if action == 'makemobi':
|
||||
tasks.make_mobi.delay(campaign)
|
||||
ebookfile = get_object_or_404(models.EbookFile, id=ebf)
|
||||
tasks.make_mobi.delay(ebookfile)
|
||||
return HttpResponseRedirect(reverse('mademobi', args=[campaign.id]))
|
||||
elif action == 'mademobi':
|
||||
alerts.append('A MOBI file is being generated')
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -63,10 +63,6 @@
|
|||
width: 660px !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#3d4e53;
|
||||
}
|
||||
|
||||
#js-search {
|
||||
margin: 0 15px 0 15px !important;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue