1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 from datetime import datetime
6 from django.shortcuts import get_object_or_404
7 from django.contrib.auth.decorators import login_required, user_passes_test
8 from django.utils import simplejson as json
9 from piston.handler import BaseHandler
10 from piston.utils import rc, validate
12 from api.models import Deleted
13 from api.helpers import timestamp
14 from catalogue.models import Book, Tag
15 from catalogue.forms import BookImportForm
16 from catalogue.views import tagged_object_list
18 class TagHandler(BaseHandler):
19 allowed_methods = ('GET',)
22 def read(self, request, tags=''):
24 return Tag.objects.all()
26 return tagged_object_list(request, tags, api=True)
28 class BookHandler(BaseHandler):
30 #fields = ('slug', 'title')
32 def read(self, request, slug=None):
34 return get_object_or_404(Book, slug=slug)
36 return Book.objects.all()
40 class WLHandler(BaseHandler):
43 def fields(request, name):
44 fields_str = request.GET.get(name) if request is not None else None
45 return fields_str.split(',') if fields_str is not None else None
48 def book_dict(book, fields=None, extra_fields=None):
50 for field in ('slug', 'title', 'description',
51 'extra_info', 'gazeta_link', 'wiki_link'):
52 if getattr(book, field):
53 obj[field] = getattr(book, field)
54 for field in ('created_at', 'changed_at'):
55 obj[field] = timestamp(getattr(book, field))
56 for field in ('xml', 'epub', 'txt', 'pdf', 'html'):
57 f = getattr(book, field+'_file')
60 for media in book.medias.all():
61 obj.setdefault(media.type, []).append(media.file.url)
63 obj['parent'] = book.parent.id
64 obj['parent_number'] = book.parent_number
65 if fields is not None:
66 for key in obj.keys():
70 # if there's still extra_info, we can parse it
71 if 'extra_info' in obj:
72 extra = json.loads(obj['extra_info'])
73 if extra_fields is not None:
74 for key in extra.keys():
75 if key not in extra_fields:
77 obj['extra_info'] = extra
83 def book_changes(cls, since=0, request=None):
84 since = datetime.fromtimestamp(float(since))
85 book_fields = cls.fields(request, 'book_fields')
86 extra_fields = cls.fields(request, 'extra_fields')
93 for book in Book.objects.filter(changed_at__gt=since):
94 if book.changed_at > last_change:
95 last_change = book.changed_at
96 book_d = cls.book_dict(book, book_fields, extra_fields)
97 if book.created_at > since:
100 changed.append(book_d)
102 for book in Deleted.objects.filter(type='Book', deleted_at__gt=since, created_at__lte=since):
103 if book.deleted_at > last_change:
104 last_change = book.deleted_at
105 deleted.append(book.id)
106 return {'added': added, 'changed': changed, 'deleted': deleted, 'last_change': timestamp(last_change)}
109 def tag_dict(tag, fields=None):
111 for field in ('name', 'slug', 'sort_key', 'category', 'description', 'main_page', #'created_at', 'changed_at',
112 'gazeta_link', 'wiki_link'):
113 if getattr(tag, field):
114 obj[field] = getattr(tag, field)
115 if fields is not None:
116 for key in obj.keys():
117 if key not in fields:
123 def tag_changes(cls, since=0, request=None):
124 since = datetime.fromtimestamp(float(since))
125 tag_fields = cls.fields(request, 'tag_fields')
132 for tag in Tag.objects.filter(changed_at__gt=since):
133 if tag.changed_at > last_change:
134 last_change = tag.changed_at
135 tag_d = cls.tag_dict(tag, tag_fields)
136 if tag.created_at > since:
139 changed.append(tag_d)
141 for tag in Deleted.objects.filter(type='Tag', deleted_at__gt=since, created_at__lte=since):
142 if tag.deleted_at > last_change:
143 last_change = tag.deleted_at
144 deleted.append(tag.id)
145 return {'added': added, 'changed': changed, 'deleted': deleted, 'last_change': timestamp(last_change)}
148 class BookChangesHandler(WLHandler):
149 allowed_methods = ('GET',)
151 def read(self, request, since):
152 return self.book_changes(since, request)
155 class TagChangesHandler(WLHandler):
156 allowed_methods = ('GET',)
158 def read(self, request, since):
159 return self.tag_changes(since, request)
162 class ChangesHandler(WLHandler):
163 allowed_methods = ('GET',)
165 def read(self, request, since):
167 'books': self.book_changes(since, request),
168 'tags': self.tag_changes(since, request),
173 for model in changes:
174 for field in changes[model]:
175 if field == 'last_change':
176 if changes[model][field] > last_change:
177 last_change = changes[model][field]
179 changes_rev.setdefault(field, {})[model] = changes[model][field]
180 changes_rev['last_change'] = last_change
187 staff_required = user_passes_test(lambda user: user.is_staff)
189 class BookHandler(BaseHandler):
191 fields = ('slug', 'title')
194 def read(self, request, slug=None):
196 return get_object_or_404(Book, slug=slug)
198 return Book.objects.all()
201 def create(self, request):
202 form = BookImportForm(request.POST, request.FILES)
207 return rc.BAD_REQUEST