From: Jan Szejko Date: Thu, 16 Jun 2016 14:33:42 +0000 (+0200) Subject: "publish" button X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/4045bf3f53908c502fbc40769a894ba2f1340d44 "publish" button --- diff --git a/apps/apiclient/__init__.py b/apps/apiclient/__init__.py index 376b66e6..485bf606 100644 --- a/apps/apiclient/__init__.py +++ b/apps/apiclient/__init__.py @@ -1,10 +1,12 @@ +# -*- coding: utf-8 -*- +import json import urllib -from django.utils import simplejson import oauth2 from apiclient.models import OAuthConnection from apiclient.settings import WL_CONSUMER_KEY, WL_CONSUMER_SECRET, WL_API_URL +from django.conf import settings if WL_CONSUMER_KEY and WL_CONSUMER_SECRET: @@ -28,23 +30,23 @@ def api_call(user, path, data=None): token = oauth2.Token(conn.token, conn.token_secret) client = oauth2.Client(wl_consumer, token) if data is not None: - data = simplejson.dumps(data) + data = json.dumps(data) data = urllib.urlencode({"data": data}) resp, content = client.request( "%s%s" % (WL_API_URL, path), method="POST", body=data) else: - resp, content = client.request( - "%s%s" % (WL_API_URL, path)) + resp, content = client.request("%s%s" % (WL_API_URL, path)) status = resp['status'] if status == '200': - return simplejson.loads(content) + return json.loads(content) elif status.startswith('2'): return + elif settings.DEBUG: + raise ApiError(content) elif status == '401': raise ApiError('User not authorized for publishing.') else: raise ApiError("WL API call error [code %s]" % status) - diff --git a/apps/apiclient/settings.py b/apps/apiclient/settings.py index f1eb34a4..fc0a63c8 100755 --- a/apps/apiclient/settings.py +++ b/apps/apiclient/settings.py @@ -1,15 +1,12 @@ +# -*- coding: utf-8 -*- from django.conf import settings WL_CONSUMER_KEY = getattr(settings, 'APICLIENT_WL_CONSUMER_KEY', None) WL_CONSUMER_SECRET = getattr(settings, 'APICLIENT_WL_CONSUMER_SECRET', None) -WL_API_URL = getattr(settings, 'APICLIENT_WL_API_URL', - 'http://wolnelektury.pl/api/') +WL_API_URL = getattr(settings, 'APICLIENT_WL_API_URL', 'https://edukacjamedialna.edu.pl/api/') -WL_REQUEST_TOKEN_URL = getattr(settings, 'APICLIENT_WL_REQUEST_TOKEN_URL', - WL_API_URL + 'oauth/request_token/') -WL_ACCESS_TOKEN_URL = getattr(settings, 'APICLIENT_WL_ACCESS_TOKEN_URL', - WL_API_URL + 'oauth/access_token/') -WL_AUTHORIZE_URL = getattr(settings, 'APICLIENT_WL_AUTHORIZE_URL', - WL_API_URL + 'oauth/authorize/') +WL_REQUEST_TOKEN_URL = getattr(settings, 'APICLIENT_WL_REQUEST_TOKEN_URL', WL_API_URL + 'oauth/request_token/') +WL_ACCESS_TOKEN_URL = getattr(settings, 'APICLIENT_WL_ACCESS_TOKEN_URL', WL_API_URL + 'oauth/access_token/') +WL_AUTHORIZE_URL = getattr(settings, 'APICLIENT_WL_AUTHORIZE_URL', WL_API_URL + 'oauth/authorize/') diff --git a/apps/apiclient/views.py b/apps/apiclient/views.py index d4960148..88f4b49b 100644 --- a/apps/apiclient/views.py +++ b/apps/apiclient/views.py @@ -1,4 +1,5 @@ -import cgi +# -*- coding: utf-8 -*- +import urlparse from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse @@ -7,8 +8,7 @@ import oauth2 from apiclient.models import OAuthConnection from apiclient import wl_consumer -from apiclient.settings import (WL_REQUEST_TOKEN_URL, WL_ACCESS_TOKEN_URL, - WL_AUTHORIZE_URL) +from apiclient.settings import (WL_REQUEST_TOKEN_URL, WL_ACCESS_TOKEN_URL, WL_AUTHORIZE_URL) @login_required @@ -21,7 +21,7 @@ def oauth(request): if resp['status'] != '200': raise Exception("Invalid response %s." % resp['status']) - request_token = dict(cgi.parse_qsl(content)) + request_token = dict(urlparse.parse_qsl(content)) conn = OAuthConnection.get(request.user) # this might reset existing auth! @@ -50,11 +50,14 @@ def oauth_callback(request): token.set_verifier(oauth_verifier) client = oauth2.Client(wl_consumer, token) resp, content = client.request(WL_ACCESS_TOKEN_URL, method="POST") - access_token = dict(cgi.parse_qsl(content)) - - conn.access = True - conn.token = access_token['oauth_token'] - conn.token_secret = access_token['oauth_token_secret'] - conn.save() + access_token = dict(urlparse.parse_qsl(content)) + + if 'oauth_token' in access_token: + conn.access = True + conn.token = access_token['oauth_token'] + conn.token_secret = access_token['oauth_token_secret'] + conn.save() + else: + return HttpResponse(request.GET.get('error')) return HttpResponseRedirect('/') diff --git a/apps/catalogue/models/book.py b/apps/catalogue/models/book.py index f40a368f..b5a3bf34 100755 --- a/apps/catalogue/models/book.py +++ b/apps/catalogue/models/book.py @@ -246,7 +246,7 @@ class Book(models.Model): def assert_publishable(self): assert self.chunk_set.exists(), _('No chunks in the book.') try: - changes = self.get_current_changes(publishable=True) + changes = self.get_current_changes() except self.NoTextError: raise AssertionError(_('Not all chunks have publishable revisions.')) @@ -254,6 +254,10 @@ class Book(models.Model): try: bi = self.wldocument(changes=changes, strict=True).book_info + if not bi.audience: + raise ValidationError('No audience specified') + if not bi.type: + raise ValidationError('No type specified') except ParseError, e: raise AssertionError(_('Invalid XML') + ': ' + unicode(e)) except NoDublinCore: @@ -399,7 +403,7 @@ class Book(models.Model): from librarian.parser import WLDocument return WLDocument.from_string( - self.materialize(publishable=publishable, changes=changes), + self.wl1_xml(publishable=publishable, changes=changes), provider=RedakcjaDocProvider(publishable=publishable), parse_dublincore=parse_dublincore, strict=strict) @@ -409,11 +413,72 @@ class Book(models.Model): Publishes a book on behalf of a (local) user. """ self.assert_publishable() - changes = self.get_current_changes(publishable=True) - book_xml = self.materialize(changes=changes) - apiclient.api_call(user, "books/", {"book_xml": book_xml}) + changes = self.get_current_changes() + book_xml = self.wl1_xml(changes=changes) + apiclient.api_call(user, "lessons/", {"lesson_xml": book_xml}) # record the publish br = BookPublishRecord.objects.create(book=self, user=user) for c in changes: ChunkPublishRecord.objects.create(book_record=br, change=c) post_publish.send(sender=br) + + def wl1_xml(self, publishable=True, changes=None): + from lxml import etree + import re + from StringIO import StringIO + from urllib import unquote + import os.path + from django.conf import settings + from fnpdjango.utils.text.slughifi import slughifi + + def _register_function(f): + """ Register extension function with lxml """ + ns = etree.FunctionNamespace('http://wolnelektury.pl/functions') + ns[f.__name__] = f + return f + + @_register_function + def slugify(context, text): + """Remove unneeded whitespace from beginning and end""" + if isinstance(text, list): + text = ''.join(text) + return slughifi(text) + + @_register_function + def rmext(context, text): + if isinstance(text, list): + text = ''.join(text) + text = unquote(text) + if '.' in text: + name, ext = text.rsplit('.', 1) + if ext.lower() in ('doc', 'docx', 'odt', 'pdf', 'jpg', 'jpeg'): + text = name + return text + + t = etree.parse(os.path.join(settings.PROJECT_ROOT, 'xslt/wl2to1.xslt')) + ft = self.materialize(publishable=publishable, changes=changes) + ft = ft.replace(' ', ' ') + f2 = StringIO(ft) + i1 = etree.parse(f2) + + for sect in i1.findall('//section'): + if sect[0].text == u'Przebieg zajęć': + # Prostujemy. + first = sect.find('section') + subs = first.findall('.//section') + for sub in subs: + sect.append(sub) + break + else: + # print 'BRAK PRZEBIEGU' + raise ValueError('Brak przebiegu') + + i1.getroot().attrib['redslug'] = self.slug + i1.getroot().attrib['wlslug'] = self.slug # THIS! + # print '.', + w1t = i1.xslt(t) + for h in w1t.findall('//aktywnosc/opis'): + if not re.match(r'\d\.\s', h[0].text): + raise AssertionError('Niepoprawny nagłówek (aktywnosc/opis): %s' % repr(h[0].text)) + h[0].text = h[0].text[3:] + return etree.tostring(w1t, encoding='utf-8') diff --git a/apps/catalogue/templates/catalogue/book_list/book.html b/apps/catalogue/templates/catalogue/book_list/book.html index 3ad8a65a..f18efc1a 100755 --- a/apps/catalogue/templates/catalogue/book_list/book.html +++ b/apps/catalogue/templates/catalogue/book_list/book.html @@ -4,6 +4,7 @@ {% with book.0 as chunk %} + [L] {{ book.title }} diff --git a/apps/catalogue/templates/catalogue/book_list/book_list.html b/apps/catalogue/templates/catalogue/book_list/book_list.html index ded59227..2a4ea736 100755 --- a/apps/catalogue/templates/catalogue/book_list/book_list.html +++ b/apps/catalogue/templates/catalogue/book_list/book_list.html @@ -16,7 +16,7 @@ - +
+ + + + + + + + + + + http://redakcja.edukacjamedialna.edu.pl/documents/book/ + + / + + + + http://edukacjamedialna.edu.pl/lekcje/ + + / + + + + + + + Fundacja Nowoczesna Polska + Creative Commons Uznanie autorstwa - Na tych samych warunkach 3.0 + http://creativecommons.org/licenses/by-sa/3.0/ + xml + + 2015-01-12 + + pol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NIEZNANA_SEKCJA + + + diff --git a/requirements.txt b/requirements.txt index 263d4196..ce3795a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ PyYAML>=3.0 Pillow oauth2 httplib2 # oauth2 dependency +texml ## Book conversion library # git+git://github.com/fnp/librarian.git@master#egg=librarian