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
eric 2016-08-24 15:41:29 -04:00
parent 651f45f624
commit 7ad0d7f494
18 changed files with 357 additions and 197 deletions

View File

@ -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),
),
]

View File

@ -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'}),
]

View File

@ -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,

View File

@ -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:

View File

@ -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():

View File

@ -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):

View File

@ -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}

View File

@ -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:

View File

@ -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 %}

View File

@ -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 />

View File

@ -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>&nbsp;&nbsp;&nbsp;
{{ 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>

View File

@ -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 %}

View File

@ -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>

View File

@ -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>

View File

@ -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"),

View File

@ -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

View File

@ -63,10 +63,6 @@
width: 660px !important;
}
a {
color:#3d4e53;
}
#js-search {
margin: 0 15px 0 15px !important;
}