Merge pull request #202 from Gluejar/b2u_fulfillment
B2u file upload, testing and watermarkingpull/1/head
commit
c5048c15b5
|
@ -0,0 +1,74 @@
|
||||||
|
import requests
|
||||||
|
from django.conf import settings
|
||||||
|
from urllib import quote
|
||||||
|
from functools import partial
|
||||||
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
|
|
||||||
|
from . exceptions import BooXtreamError
|
||||||
|
from . models import Boox
|
||||||
|
|
||||||
|
|
||||||
|
class BooXtream(object):
|
||||||
|
""" ``apikey``
|
||||||
|
|
||||||
|
The API key for your BooXtream account, obtained from BooXtream. Defaults to using
|
||||||
|
settings.BOOXTREAM_API_KEY
|
||||||
|
|
||||||
|
``apiuser``
|
||||||
|
|
||||||
|
The username key for your BooXtream account, obtained from BooXtream. Defaults to using
|
||||||
|
settings.BOOXTREAM_API_USER
|
||||||
|
|
||||||
|
|
||||||
|
``timeout``
|
||||||
|
|
||||||
|
passed to requests
|
||||||
|
"""
|
||||||
|
def __init__(self,
|
||||||
|
apikey='', apiuser='',
|
||||||
|
timeout=None,
|
||||||
|
**params):
|
||||||
|
if not apikey:
|
||||||
|
apikey = settings.BOOXTREAM_API_KEY
|
||||||
|
if not apiuser:
|
||||||
|
apiuser = settings.BOOXTREAM_API_USER
|
||||||
|
self.endpoint = 'http://service.booxtream.com/'
|
||||||
|
self.postrequest = partial(requests.post, timeout=timeout, auth=(apiuser,apikey))
|
||||||
|
|
||||||
|
|
||||||
|
def platform(self, epubfile=None, epub=True, kf8mobi=False, **kwargs):
|
||||||
|
""" Make an API request to BooXtream
|
||||||
|
``self.apikey``, ``epubfile`` and the supplied ``kwargs``.
|
||||||
|
Attempts to deserialize the XML response and return the download link.
|
||||||
|
|
||||||
|
Will raise ``BooXtreamError`` if BooXtream returns an exception
|
||||||
|
code.
|
||||||
|
"""
|
||||||
|
url = self.endpoint + 'booxtream.xml'
|
||||||
|
kwargs['epub'] = '1' if epub else '0'
|
||||||
|
kwargs['kf8mobi'] = '1' if kf8mobi else '0'
|
||||||
|
|
||||||
|
files= {'epubfile': epubfile} if epubfile else {}
|
||||||
|
resp = self.postrequest(url, data=kwargs, files=files)
|
||||||
|
doc = ElementTree.fromstring(resp.content)
|
||||||
|
|
||||||
|
# it turns out an Error can have an Error in it
|
||||||
|
errors = doc.findall('.//Response/Error')
|
||||||
|
if len(errors) > 0:
|
||||||
|
raise BooXtreamError(errors)
|
||||||
|
download_link_epub = doc.find('.//DownloadLink[@type="epub"]')
|
||||||
|
if download_link_epub is not None:
|
||||||
|
download_link_epub = download_link_epub.text
|
||||||
|
download_link_mobi = doc.find('.//DownloadLink[@type="mobi"]')
|
||||||
|
if download_link_mobi is not None:
|
||||||
|
download_link_mobi = download_link_mobi.text
|
||||||
|
boox = Boox.objects.create(
|
||||||
|
download_link_epub=download_link_epub,
|
||||||
|
download_link_mobi=download_link_mobi,
|
||||||
|
referenceid= kwargs.get('referenceid'),
|
||||||
|
downloads_remaining= kwargs.get('downloadlimit'),
|
||||||
|
expirydays=kwargs.get('expirydays'),
|
||||||
|
)
|
||||||
|
return boox
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
|
||||||
|
class BooXtreamError(Exception):
|
||||||
|
""" list of errors returned in xml
|
||||||
|
"""
|
||||||
|
def __init__(self, errors):
|
||||||
|
self.errors = errors
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
errormsg='BooXtream errors:'
|
||||||
|
for error in self.errors:
|
||||||
|
errormsg += 'Error %s: %s\n'% (error.find('Code').text,error.find('Msg').text)
|
||||||
|
return errormsg
|
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import SchemaMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(SchemaMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
# Adding model 'Boox'
|
||||||
|
db.create_table('booxtream_boox', (
|
||||||
|
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||||
|
('download_link_epub', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)),
|
||||||
|
('download_link_mobi', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)),
|
||||||
|
('referenceid', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||||
|
('downloads_remaining', self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0)),
|
||||||
|
('expirydays', self.gf('django.db.models.fields.PositiveSmallIntegerField')()),
|
||||||
|
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||||
|
))
|
||||||
|
db.send_create_signal('booxtream', ['Boox'])
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
# Deleting model 'Boox'
|
||||||
|
db.delete_table('booxtream_boox')
|
||||||
|
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'booxtream.boox': {
|
||||||
|
'Meta': {'object_name': 'Boox'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'download_link_epub': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
|
||||||
|
'download_link_mobi': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
|
||||||
|
'downloads_remaining': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||||
|
'expirydays': ('django.db.models.fields.PositiveSmallIntegerField', [], {}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'referenceid': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['booxtream']
|
|
@ -0,0 +1,19 @@
|
||||||
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Boox(models.Model):
|
||||||
|
"""
|
||||||
|
keeps a record of a file that's been watermarked
|
||||||
|
"""
|
||||||
|
download_link_epub = models.URLField(null=True)
|
||||||
|
download_link_mobi = models.URLField(null=True)
|
||||||
|
referenceid = models.CharField(max_length=32)
|
||||||
|
downloads_remaining = models.PositiveSmallIntegerField(default = 0)
|
||||||
|
expirydays = models.PositiveSmallIntegerField()
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def expired(self):
|
||||||
|
return self.created+timedelta(days=self.expirydays) < datetime.now()
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
This is a thin Python (2.6+) wrapper for BooXtream's API for watermarking epub files. It's configured to look for parameters in Django settings files:
|
||||||
|
BOOXTREAM_API_KEY = ''
|
||||||
|
BOOXTREAM_API_USER = ''
|
||||||
|
BOOXTREAM_TEST_EPUB = ''
|
||||||
|
|
||||||
|
http://www.booxtream.com/
|
||||||
|
version 2.52.
|
||||||
|
|
||||||
|
Currently, only the platform method is implemented.
|
||||||
|
|
||||||
|
See Tests for usage
|
||||||
|
|
||||||
|
Eric Hellman August 2013
|
||||||
|
Apache license
|
|
@ -0,0 +1,38 @@
|
||||||
|
import unittest
|
||||||
|
import time
|
||||||
|
|
||||||
|
# uses settings.BOOXTREAM_TEST_EPUB
|
||||||
|
from . import settings
|
||||||
|
|
||||||
|
class TestBooXtream(unittest.TestCase):
|
||||||
|
def _makeOne(self):
|
||||||
|
from . import BooXtream
|
||||||
|
manager = BooXtream()
|
||||||
|
return manager
|
||||||
|
|
||||||
|
def test_booxtream_errors(self):
|
||||||
|
from .exceptions import BooXtreamError
|
||||||
|
inst = self._makeOne()
|
||||||
|
with self.assertRaises(BooXtreamError) as cm:
|
||||||
|
inst.platform()
|
||||||
|
self.assertIn( 'expirydays not set',str(cm.exception))
|
||||||
|
|
||||||
|
|
||||||
|
def test_booxtream_good(self):
|
||||||
|
inst = self._makeOne()
|
||||||
|
params={
|
||||||
|
'customeremailaddress':'jane@example.com',
|
||||||
|
'customername': 'Jane Test',
|
||||||
|
'languagecode':'1043',
|
||||||
|
'expirydays': 1,
|
||||||
|
'downloadlimit': 3,
|
||||||
|
'exlibris':1,
|
||||||
|
'chapterfooter':1,
|
||||||
|
'disclaimer':1,
|
||||||
|
}
|
||||||
|
params['referenceid']= 'order'+str(time.time())
|
||||||
|
epubfile= open(settings.BOOXTREAM_TEST_EPUB)
|
||||||
|
boox=inst.platform(epubfile=epubfile, **params)
|
||||||
|
self.assertRegexpMatches(boox.download_link_epub,'download.booxtream.com/')
|
||||||
|
self.assertFalse(boox.expired)
|
||||||
|
self.assertEqual(boox.downloads_remaining,3)
|
|
@ -0,0 +1,319 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import SchemaMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(SchemaMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
# Adding field 'Acq.watermarked'
|
||||||
|
db.add_column('core_acq', 'watermarked',
|
||||||
|
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['booxtream.Boox'], null=True),
|
||||||
|
keep_default=False)
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
# Deleting field 'Acq.watermarked'
|
||||||
|
db.delete_column('core_acq', 'watermarked_id')
|
||||||
|
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'auth.permission': {
|
||||||
|
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
'booxtream.boox': {
|
||||||
|
'Meta': {'object_name': 'Boox'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'download_link_epub': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
|
||||||
|
'download_link_mobi': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
|
||||||
|
'downloads_remaining': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
|
||||||
|
'expirydays': ('django.db.models.fields.PositiveSmallIntegerField', [], {}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'referenceid': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||||
|
},
|
||||||
|
'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'core.acq': {
|
||||||
|
'Meta': {'object_name': 'Acq'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'license': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'acqs'", 'to': "orm['auth.User']"}),
|
||||||
|
'watermarked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['booxtream.Boox']", 'null': 'True'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'acqs'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.author': {
|
||||||
|
'Meta': {'object_name': 'Author'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
|
||||||
|
},
|
||||||
|
'core.badge': {
|
||||||
|
'Meta': {'object_name': 'Badge'},
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '72', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'core.campaign': {
|
||||||
|
'Meta': {'object_name': 'Campaign'},
|
||||||
|
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'cc_date_initial': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'deadline': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
|
||||||
|
'description': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
|
||||||
|
'details': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'dollar_per_day': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'license': ('django.db.models.fields.CharField', [], {'default': "'CC BY-NC-ND'", 'max_length': '255'}),
|
||||||
|
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
|
||||||
|
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'publisher': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'null': 'True', 'to': "orm['core.Publisher']"}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
|
||||||
|
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'type': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.campaignaction': {
|
||||||
|
'Meta': {'object_name': 'CampaignAction'},
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
|
||||||
|
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
|
||||||
|
},
|
||||||
|
'core.celerytask': {
|
||||||
|
'Meta': {'object_name': 'CeleryTask'},
|
||||||
|
'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 8, 26, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}),
|
||||||
|
'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
|
||||||
|
'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'core.claim': {
|
||||||
|
'Meta': {'object_name': 'Claim'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.ebook': {
|
||||||
|
'Meta': {'object_name': 'Ebook'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'download_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
|
||||||
|
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
|
||||||
|
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
|
||||||
|
},
|
||||||
|
'core.ebookfile': {
|
||||||
|
'Meta': {'object_name': 'EbookFile'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebook_files'", 'to': "orm['core.Edition']"}),
|
||||||
|
'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
|
||||||
|
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'core.edition': {
|
||||||
|
'Meta': {'object_name': 'Edition'},
|
||||||
|
'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'publisher_name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.PublisherName']"}),
|
||||||
|
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||||
|
'unglued': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.identifier': {
|
||||||
|
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
|
||||||
|
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.key': {
|
||||||
|
'Meta': {'object_name': 'Key'},
|
||||||
|
'encrypted_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
|
||||||
|
},
|
||||||
|
'core.libpref': {
|
||||||
|
'Meta': {'object_name': 'Libpref'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'marc_link_target': ('django.db.models.fields.CharField', [], {'default': "'UNGLUE'", 'max_length': '6'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'libpref'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'core.marcrecord': {
|
||||||
|
'Meta': {'object_name': 'MARCRecord'},
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'MARCrecords'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'link_target': ('django.db.models.fields.CharField', [], {'default': "'DIRECT'", 'max_length': '6'}),
|
||||||
|
'mrc_record': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'xml_record': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'core.offer': {
|
||||||
|
'Meta': {'object_name': 'Offer'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'license': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
|
||||||
|
'price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'offers'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.premium': {
|
||||||
|
'Meta': {'object_name': 'Premium'},
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'limit': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
|
||||||
|
},
|
||||||
|
'core.press': {
|
||||||
|
'Meta': {'object_name': 'Press'},
|
||||||
|
'date': ('django.db.models.fields.DateField', [], {}),
|
||||||
|
'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'language': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
|
||||||
|
'note': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
|
||||||
|
'source': ('django.db.models.fields.CharField', [], {'max_length': '140'}),
|
||||||
|
'title': ('django.db.models.fields.CharField', [], {'max_length': '140'}),
|
||||||
|
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
|
||||||
|
},
|
||||||
|
'core.publisher': {
|
||||||
|
'Meta': {'object_name': 'Publisher'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_publisher'", 'to': "orm['core.PublisherName']"}),
|
||||||
|
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'core.publishername': {
|
||||||
|
'Meta': {'object_name': 'PublisherName'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'publisher': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternate_names'", 'null': 'True', 'to': "orm['core.Publisher']"})
|
||||||
|
},
|
||||||
|
'core.rightsholder': {
|
||||||
|
'Meta': {'object_name': 'RightsHolder'},
|
||||||
|
'can_sell': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
|
||||||
|
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'core.subject': {
|
||||||
|
'Meta': {'ordering': "['name']", 'object_name': 'Subject'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
|
||||||
|
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.userprofile': {
|
||||||
|
'Meta': {'object_name': 'UserProfile'},
|
||||||
|
'avatar_source': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1', 'null': 'True'}),
|
||||||
|
'badges': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'holders'", 'symmetrical': 'False', 'to': "orm['core.Badge']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
|
||||||
|
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'kindle_email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'blank': 'True'}),
|
||||||
|
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
|
||||||
|
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
|
||||||
|
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'core.waswork': {
|
||||||
|
'Meta': {'object_name': 'WasWork'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'moved': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
|
||||||
|
'was': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.wishes': {
|
||||||
|
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
|
||||||
|
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wishes'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.wishlist': {
|
||||||
|
'Meta': {'object_name': 'Wishlist'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
|
||||||
|
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.work': {
|
||||||
|
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
|
||||||
|
'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
|
||||||
|
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['core']
|
|
@ -47,7 +47,19 @@ from regluit.payment.parameters import (
|
||||||
TRANSACTION_STATUS_FAILED,
|
TRANSACTION_STATUS_FAILED,
|
||||||
TRANSACTION_STATUS_INCOMPLETE
|
TRANSACTION_STATUS_INCOMPLETE
|
||||||
)
|
)
|
||||||
from regluit.core.parameters import *
|
|
||||||
|
from regluit.core.parameters import (
|
||||||
|
REWARDS,
|
||||||
|
BUY2UNGLUE,
|
||||||
|
INDIVIDUAL,
|
||||||
|
LIBRARY,
|
||||||
|
BORROWED,
|
||||||
|
TESTING
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
from regluit.booxtream import BooXtream
|
||||||
|
watermarker = BooXtream()
|
||||||
|
|
||||||
pm = PostMonkey(settings.MAILCHIMP_API_KEY)
|
pm = PostMonkey(settings.MAILCHIMP_API_KEY)
|
||||||
|
|
||||||
|
@ -226,7 +238,6 @@ class CCLicense():
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
(INDIVIDUAL, LIBRARY, BORROWED) = (1, 2, 3)
|
|
||||||
class Offer(models.Model):
|
class Offer(models.Model):
|
||||||
CHOICES = ((INDIVIDUAL,'Individual license'),(LIBRARY,'Library License'))
|
CHOICES = ((INDIVIDUAL,'Individual license'),(LIBRARY,'Library License'))
|
||||||
work = models.ForeignKey("Work", related_name="offers", null=False)
|
work = models.ForeignKey("Work", related_name="offers", null=False)
|
||||||
|
@ -244,13 +255,33 @@ class Acq(models.Model):
|
||||||
"""
|
"""
|
||||||
Short for Acquisition, this is a made-up word to describe the thing you acquire when you buy or borrow an ebook
|
Short for Acquisition, this is a made-up word to describe the thing you acquire when you buy or borrow an ebook
|
||||||
"""
|
"""
|
||||||
CHOICES = ((INDIVIDUAL,'Individual license'),(LIBRARY,'Library License'),(BORROWED,'Borrowed from Library'))
|
CHOICES = ((INDIVIDUAL,'Individual license'),(LIBRARY,'Library License'),(BORROWED,'Borrowed from Library'), (TESTING,'Just for Testing'))
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
expires = models.DateTimeField(null=True)
|
expires = models.DateTimeField(null=True)
|
||||||
work = models.ForeignKey("Work", related_name='acqs', null=False)
|
work = models.ForeignKey("Work", related_name='acqs', null=False)
|
||||||
user = models.ForeignKey(User, related_name='acqs')
|
user = models.ForeignKey(User, related_name='acqs')
|
||||||
license = models.PositiveSmallIntegerField(null = False, default = INDIVIDUAL,
|
license = models.PositiveSmallIntegerField(null = False, default = INDIVIDUAL,
|
||||||
choices=CHOICES)
|
choices=CHOICES)
|
||||||
|
watermarked = models.ForeignKey("booxtream.Boox", null=True)
|
||||||
|
|
||||||
|
def get_epub_url(self):
|
||||||
|
if self.watermarked == None or self.watermarked.expired:
|
||||||
|
params={
|
||||||
|
'customeremailaddress': self.user.email,
|
||||||
|
'customername': self.user.username,
|
||||||
|
'languagecode':'1043',
|
||||||
|
'expirydays': 1,
|
||||||
|
'downloadlimit': 7,
|
||||||
|
'exlibris':1,
|
||||||
|
'chapterfooter':1,
|
||||||
|
'disclaimer':1,
|
||||||
|
'referenceid': '%s:%s:%s' % (self.work.id, self.user.id, self.id),
|
||||||
|
'kf8mobi': True,
|
||||||
|
'epub': True,
|
||||||
|
}
|
||||||
|
self.watermarked = watermarker.platform(epubfile= self.work.ebookfiles()[0].file, **params)
|
||||||
|
self.save()
|
||||||
|
return self.watermarked.download_link_epub
|
||||||
|
|
||||||
class Campaign(models.Model):
|
class Campaign(models.Model):
|
||||||
LICENSE_CHOICES = settings.CCCHOICES
|
LICENSE_CHOICES = settings.CCCHOICES
|
||||||
|
@ -870,7 +901,7 @@ class Work(models.Model):
|
||||||
return Ebook.objects.filter(edition__work=self).order_by('-created')
|
return Ebook.objects.filter(edition__work=self).order_by('-created')
|
||||||
|
|
||||||
def ebookfiles(self):
|
def ebookfiles(self):
|
||||||
return EbookFile.objects.filter(edition__work=self).order_by('format')
|
return EbookFile.objects.filter(edition__work=self).order_by('-created')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def download_count(self):
|
def download_count(self):
|
||||||
|
@ -986,7 +1017,7 @@ class Work(models.Model):
|
||||||
def purchased_by(self,user):
|
def purchased_by(self,user):
|
||||||
if user==None or not user.is_authenticated():
|
if user==None or not user.is_authenticated():
|
||||||
return False
|
return False
|
||||||
acqs= Acq.objects.filter(user=user,work=self)
|
acqs= self.acqs.filter(user=user)
|
||||||
if acqs.count()==0:
|
if acqs.count()==0:
|
||||||
return False
|
return False
|
||||||
for acq in acqs:
|
for acq in acqs:
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
(REWARDS, BUY2UNGLUE) = (1, 2)
|
(REWARDS, BUY2UNGLUE) = (1, 2)
|
||||||
|
(INDIVIDUAL, LIBRARY, BORROWED) = (1, 2, 3)
|
||||||
|
TESTING = 0
|
||||||
|
|
|
@ -184,9 +184,11 @@ def handle_transaction_charged(sender,transaction=None, **kwargs):
|
||||||
else:
|
else:
|
||||||
# provision the book
|
# provision the book
|
||||||
Acq = get_model('core', 'Acq')
|
Acq = get_model('core', 'Acq')
|
||||||
Acq.objects.create(user=transaction.user,work=transaction.campaign.work,license= transaction.offer.license)
|
new_acq = Acq.objects.create(user=transaction.user,work=transaction.campaign.work,license= transaction.offer.license)
|
||||||
transaction.campaign.update_left()
|
transaction.campaign.update_left()
|
||||||
notification.send([transaction.user], "purchase_complete", {'transaction':transaction}, True)
|
notification.send([transaction.user], "purchase_complete", {'transaction':transaction}, True)
|
||||||
|
from regluit.core.tasks import watermark_acq
|
||||||
|
watermark_acq(new_acq).delay()
|
||||||
from regluit.core.tasks import emit_notifications
|
from regluit.core.tasks import emit_notifications
|
||||||
emit_notifications.delay()
|
emit_notifications.delay()
|
||||||
|
|
||||||
|
|
|
@ -121,5 +121,7 @@ def notify_ending_soon():
|
||||||
"""
|
"""
|
||||||
deadline_impending.send(sender=None, campaign=c)
|
deadline_impending.send(sender=None, campaign=c)
|
||||||
|
|
||||||
|
@task
|
||||||
|
def watermark_acq(acq):
|
||||||
|
acq.get_epub_url()
|
||||||
|
|
|
@ -6,8 +6,11 @@ from decimal import Decimal as D
|
||||||
from math import factorial
|
from math import factorial
|
||||||
from time import sleep, mktime
|
from time import sleep, mktime
|
||||||
from urlparse import parse_qs, urlparse
|
from urlparse import parse_qs, urlparse
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
from celery.task import chord
|
from celery.task import chord
|
||||||
from celery.task.sets import TaskSet
|
from celery.task.sets import TaskSet
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
|
||||||
"""
|
"""
|
||||||
django imports
|
django imports
|
||||||
|
@ -17,6 +20,7 @@ from django.contrib.auth.models import User
|
||||||
from django.contrib.comments.models import Comment
|
from django.contrib.comments.models import Comment
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
from django.core.files import File as DjangoFile
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -49,7 +53,11 @@ from regluit.core.models import (
|
||||||
Subject,
|
Subject,
|
||||||
Publisher,
|
Publisher,
|
||||||
Offer,
|
Offer,
|
||||||
|
EbookFile,
|
||||||
|
Acq,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from regluit.core.parameters import TESTING
|
||||||
from regluit.frontend.views import safe_get_work
|
from regluit.frontend.views import safe_get_work
|
||||||
from regluit.payment.models import Transaction
|
from regluit.payment.models import Transaction
|
||||||
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
|
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
|
||||||
|
@ -812,4 +820,40 @@ class MailingListTests(TestCase):
|
||||||
self.user = User.objects.create_user('chimp_test', 'eric@gluejar.com', 'chimp_test')
|
self.user = User.objects.create_user('chimp_test', 'eric@gluejar.com', 'chimp_test')
|
||||||
self.assertTrue(self.user.profile.on_ml)
|
self.assertTrue(self.user.profile.on_ml)
|
||||||
|
|
||||||
|
class EbookFileTests(TestCase):
|
||||||
|
|
||||||
|
def test_ebookfile(self):
|
||||||
|
"""
|
||||||
|
Read the test epub file
|
||||||
|
"""
|
||||||
|
w = Work.objects.create(title="Work 1")
|
||||||
|
e = Edition.objects.create(title=w.title,work=w)
|
||||||
|
u = User.objects.create_user('test', 'test@example.org', 'testpass')
|
||||||
|
|
||||||
|
# download the test epub into a temp file
|
||||||
|
temp = NamedTemporaryFile(delete=False)
|
||||||
|
test_file_content = requests.get(settings.BOOXTREAM_TEST_EPUB_URL).content
|
||||||
|
|
||||||
|
temp.write(test_file_content)
|
||||||
|
temp.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# now we can try putting the test epub file into Django storage
|
||||||
|
temp_file = open(temp.name)
|
||||||
|
|
||||||
|
dj_file = DjangoFile(temp_file)
|
||||||
|
ebf = EbookFile( format='epub', edition=e, file=dj_file)
|
||||||
|
ebf.save()
|
||||||
|
|
||||||
|
temp_file.close()
|
||||||
|
finally:
|
||||||
|
# make sure we get rid of temp file
|
||||||
|
os.remove(temp.name)
|
||||||
|
|
||||||
|
|
||||||
|
acq=Acq.objects.create(user=u,work=w,license=TESTING)
|
||||||
|
url= acq.get_epub_url()
|
||||||
|
self.assertRegexpMatches(url,'download.booxtream.com/')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ from regluit.core.lookups import (
|
||||||
EditionLookup
|
EditionLookup
|
||||||
)
|
)
|
||||||
from regluit.utils.localdatetime import now
|
from regluit.utils.localdatetime import now
|
||||||
|
from regluit.utils.fields import EpubFileField
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -135,10 +136,15 @@ class EditionForm(forms.ModelForm):
|
||||||
'add_subject': forms.TextInput(attrs={'size': 30}),
|
'add_subject': forms.TextInput(attrs={'size': 30}),
|
||||||
'unglued': forms.CheckboxInput(),
|
'unglued': forms.CheckboxInput(),
|
||||||
}
|
}
|
||||||
|
|
||||||
class EbookFileForm(forms.ModelForm):
|
class EbookFileForm(forms.ModelForm):
|
||||||
|
file = EpubFileField(max_length=16777216)
|
||||||
|
def clean_format(self):
|
||||||
|
return 'epub'
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = EbookFile
|
model = EbookFile
|
||||||
widgets = { 'edition': forms.HiddenInput, }
|
widgets = { 'edition': forms.HiddenInput, 'format': forms.HiddenInput }
|
||||||
exclude = { 'created', }
|
exclude = { 'created', }
|
||||||
|
|
||||||
class EbookForm(forms.ModelForm):
|
class EbookForm(forms.ModelForm):
|
||||||
|
|
|
@ -20,15 +20,31 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% if edition.ebook_files.all %}
|
{% if edition.ebook_files.all %}
|
||||||
<h2> Ebook Files for this Edition</h2>
|
<h2> Ebook Files for this Edition</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{% for ebook_file in edition.ebook_files.all %}
|
{% for ebook_file in edition.ebook_files.all %}
|
||||||
<li>{{ebook_file.file}} created {{ebook_file.created}} </li>
|
<li>{{ebook_file.file}} created {{ebook_file.created}} </li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% if uploaded %}
|
||||||
|
<h2> Your file was successfully loaded. </h2>
|
||||||
|
{% if watermarked %}
|
||||||
|
<p> Reference id: <b>{{watermarked.referenceid}}</b></p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{watermarked.download_link_epub}}">Watermarked epub for testing</a></li>
|
||||||
|
<li><a href="{{watermarked.download_link_mobi}}">Watermarked mobi for testing</a></li>
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
<span class="yikes">Unfortunately, your file failed testing.</span>
|
||||||
|
The error(s) were: <pre>
|
||||||
|
{{ upload_error }}</pre>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h2>Upload Ebook files</h2>
|
<h2>Upload Ebook files</h2>
|
||||||
|
<p>At this time, we accept only EPUB files for "Buy to Unglue" campaigns. 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">
|
<form method="POST" action="#" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{form.as_p}}
|
{{form.as_p}}
|
||||||
|
|
|
@ -54,10 +54,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="find-book">
|
<div class="find-book">
|
||||||
<label>Available formats...</label>
|
<h4>Available formats...</h4>
|
||||||
{% for ebookfile in work.ebookfiles %}
|
<ul>
|
||||||
<span class="format_display"><img src="/static/images/{{ ebookfile.format }}32.png" height="32" alt="{{ ebookfile.get_format_display }}" title="{{ ebookfile.get_format_display }}" /></span>
|
<li><span class="format_display"><img src="/static/images/mobi32.png" height="32" alt="mobi" title="mobi" /> (for Kindle) </span></li>
|
||||||
{% endfor %}
|
<li><span class="format_display"><img src="/static/images/epub32.png" height="32" alt="epub" title="epub" /> (for iBooks, Readmill, Nook, Kobo) </span></li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -134,6 +134,7 @@ from regluit.payment.parameters import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from regluit.utils.localdatetime import now, date_today
|
from regluit.utils.localdatetime import now, date_today
|
||||||
|
from regluit.booxtream.exceptions import BooXtreamError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -424,6 +425,7 @@ def work(request, work_id, action='display'):
|
||||||
})
|
})
|
||||||
|
|
||||||
def edition_uploads(request, edition_id):
|
def edition_uploads(request, edition_id):
|
||||||
|
context = {}
|
||||||
if not request.user.is_authenticated() :
|
if not request.user.is_authenticated() :
|
||||||
return render(request, "admins_only.html")
|
return render(request, "admins_only.html")
|
||||||
try:
|
try:
|
||||||
|
@ -437,13 +439,22 @@ def edition_uploads(request, edition_id):
|
||||||
form = EbookFileForm(request.POST,request.FILES)
|
form = EbookFileForm(request.POST,request.FILES)
|
||||||
if form.is_valid() :
|
if form.is_valid() :
|
||||||
form.save()
|
form.save()
|
||||||
|
context['uploaded']=True
|
||||||
|
# campaign mangager gets a copy
|
||||||
|
test_acq = models.Acq.objects.create(user=request.user,work=edition.work,license= TESTING)
|
||||||
|
try:
|
||||||
|
test_acq.get_epub_url()
|
||||||
|
context['watermarked']= test_acq.watermarked
|
||||||
|
except (BooXtreamError, ET.ParseError) as e:
|
||||||
|
context['upload_error']= e
|
||||||
|
form.instance.delete()
|
||||||
|
|
||||||
else:
|
form = EbookFileForm(initial={'edition':edition,'format':'epub'})
|
||||||
form = EbookFileForm(initial={'edition':edition})
|
context.update({
|
||||||
return render(request, 'edition_uploads.html', {
|
|
||||||
'form': form, 'edition': edition,
|
'form': form, 'edition': edition,
|
||||||
'ebook_files': models.EbookFile.objects.filter(edition = edition)
|
'ebook_files': models.EbookFile.objects.filter(edition = edition)
|
||||||
})
|
})
|
||||||
|
return render(request, 'edition_uploads.html', context )
|
||||||
|
|
||||||
|
|
||||||
def new_edition(request, work_id, edition_id, by=None):
|
def new_edition(request, work_id, edition_id, by=None):
|
||||||
|
@ -1091,6 +1102,7 @@ class PurchaseView(PledgeView):
|
||||||
template_name="purchase.html"
|
template_name="purchase.html"
|
||||||
form_class = CampaignPurchaseForm
|
form_class = CampaignPurchaseForm
|
||||||
action = "purchase"
|
action = "purchase"
|
||||||
|
offer_id = None
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(PledgeView, self).get_context_data(**kwargs)
|
context = super(PledgeView, self).get_context_data(**kwargs)
|
||||||
|
@ -1100,7 +1112,8 @@ class PurchaseView(PledgeView):
|
||||||
'faqmenu': 'purchase' ,
|
'faqmenu': 'purchase' ,
|
||||||
'transaction': self.transaction,
|
'transaction': self.transaction,
|
||||||
'tid': self.transaction.id if self.transaction else None,
|
'tid': self.transaction.id if self.transaction else None,
|
||||||
'cover_width': cover_width(self.work)
|
'cover_width': cover_width(self.work),
|
||||||
|
'offer_id':self.offer_id,
|
||||||
})
|
})
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
@ -1117,10 +1130,9 @@ class PurchaseView(PledgeView):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
# this used to raise an exception, but that seemed pointless. This now has the effect of preventing any pledges.
|
# this used to raise an exception, but that seemed pointless. This now has the effect of preventing any pledges.
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
self.data = {
|
self.data = {
|
||||||
'preapproval_amount':self.get_preapproval_amount(),
|
'preapproval_amount':self.get_preapproval_amount(),
|
||||||
'anonymous':self.request.user.profile.anon_pref
|
'anonymous':self.request.user.profile.anon_pref,
|
||||||
}
|
}
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
self.data.update(self.request.POST.dict())
|
self.data.update(self.request.POST.dict())
|
||||||
|
@ -1131,11 +1143,13 @@ class PurchaseView(PledgeView):
|
||||||
return {'initial':self.data}
|
return {'initial':self.data}
|
||||||
|
|
||||||
def get_preapproval_amount(self):
|
def get_preapproval_amount(self):
|
||||||
offer_id = self.request.REQUEST.get('offer_id', None)
|
self.offer_id = self.request.REQUEST.get('offer_id', None)
|
||||||
|
if not self.offer_id:
|
||||||
|
self.offer_id = self.work.last_campaign().active_offers()[0].id
|
||||||
preapproval_amount = None
|
preapproval_amount = None
|
||||||
if offer_id != None:
|
if self.offer_id != None:
|
||||||
try:
|
try:
|
||||||
preapproval_amount = D(models.Offer.objects.get(id=offer_id).price)
|
preapproval_amount = D(models.Offer.objects.get(id=self.offer_id).price)
|
||||||
except:
|
except:
|
||||||
preapproval_amount = None
|
preapproval_amount = None
|
||||||
return preapproval_amount
|
return preapproval_amount
|
||||||
|
|
|
@ -148,6 +148,7 @@ INSTALLED_APPS = (
|
||||||
# this must appear *after* django.frontend or else it overrides the
|
# this must appear *after* django.frontend or else it overrides the
|
||||||
# registration templates in frontend/templates/registration
|
# registration templates in frontend/templates/registration
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
|
'booxtream',
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -407,3 +408,7 @@ MARC_CHOICES = (
|
||||||
('UNGLUE', 'Unglue.it link'),
|
('UNGLUE', 'Unglue.it link'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
BOOXTREAM_API_KEY = '7ynRCsx4q21zEY67it7yk8u5rc6EXY'
|
||||||
|
BOOXTREAM_API_USER = 'ungluetest'
|
||||||
|
BOOXTREAM_TEST_EPUB_URL = 'https://github.com/Gluejar/open_access_ebooks_ebook/raw/master/download/open_access_ebooks.epub'
|
||||||
|
FILE_UPLOAD_MAX_MEMORY_SIZE = 20971520 #20MB
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
import zipfile
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.template.defaultfilters import filesizeformat
|
||||||
|
|
||||||
|
class EpubFileField(forms.FileField):
|
||||||
|
"""
|
||||||
|
does some epub checking; currently only checks its a zip:
|
||||||
|
"""
|
||||||
|
def clean(self, data, initial=None):
|
||||||
|
data = super(EpubFileField, self).clean(data, initial)
|
||||||
|
if data.name and not zipfile.is_zipfile(data.file):
|
||||||
|
raise forms.ValidationError(_('%s is not a valid EPUB file' % data.name) )
|
||||||
|
return data
|
Loading…
Reference in New Issue