bugfixing simple api and tests
[mygpo.git] / mygpo / api / simple.py
blobe7550d9761b80cac3817bed5341021d17a573757
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from mygpo.api.basic_auth import require_valid_user
19 from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404
20 from mygpo.api.models import Device, SubscriptionAction, Podcast, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION
21 from mygpo.api.opml import Exporter, Importer
22 from mygpo.api.httpresponse import JsonResponse
23 from django.core import serializers
24 from datetime import datetime
25 from mygpo.api.httpresponse import HttpResponseNotAuthorized
26 import re
27 from mygpo.log import log
29 try:
30 import simplejson as json
31 except ImportError:
32 import json
34 @require_valid_user
35 def subscriptions(request, username, device_uid, format):
37 if request.user.username != username:
38 #throw 401
39 return HttpResponseNotAuthorized()
41 if request.method == 'GET':
42 return format_subscriptions(get_subscriptions(request.user, device_uid), format, username)
44 elif request.method == 'PUT':
45 return set_subscriptions(parse_subscription(request.raw_post_data, format, request.user, device_uid))
46 else:
47 return HttpResponseBadReqest()
50 def format_subscriptions(subscriptions, format, username):
51 if format == 'txt':
52 #return subscriptions formatted as txt
53 urls = [p.url for p in subscriptions]
54 s = '\n'.join(urls)
55 s += '\n'
56 return HttpResponse(s, mimetype='text/plain')
58 elif format == 'opml':
59 title = username + '\'s subscription list'
60 exporter = Exporter(title)
61 opml = exporter.generate(subscriptions)
62 return HttpResponse(opml, mimetype='text/xml')
64 elif format == 'json':
65 urls = [p.url for p in subscriptions]
66 return JsonResponse(urls)
68 def get_subscriptions(user, device_uid):
69 #get and return subscription list from database (use backend to sync)
70 try:
71 d = Device.objects.get(uid=device_uid, user=user)
72 except Device.DoesNotExist:
73 raise Http404('Device doesn\'t exist!')
74 return [p.podcast for p in d.get_subscriptions()]
76 def parse_subscription(raw_post_data, format, user, device_uid):
77 if format == 'txt':
78 sub = raw_post_data.split('\n')
79 p = '^[a-zA-z]'
80 urls = []
81 for x in sub:
82 if re.search(p, x) == None:
83 log('parse_subscription (txt): invalid podcast url: %s' % x)
84 else:
85 urls.append(x)
87 elif format == 'opml':
88 i = Importer(content=raw_post_data)
89 urls = [p['url'] for p in i.items]
91 elif format == 'json':
92 urls = json.loads(raw_post_data)
94 else: raise ValueError('unsupported format %s' % format)
96 d, created = Device.objects.get_or_create(user=user, uid=device_uid,
97 defaults = {'type': 'other', 'name': device_uid})
99 podcasts = [p.podcast for p in d.get_subscriptions()]
100 old = [p.url for p in podcasts]
101 new = [p for p in urls if p not in old]
102 rem = [p for p in old if p not in urls]
104 return new, rem, d
106 def set_subscriptions(subscriptions):
107 new, rem, d = subscriptions
109 for r in rem:
110 p = Podcast.objects.get(url=r)
111 s = SubscriptionAction(podcast=p, device=d, action=UNSUBSCRIBE_ACTION)
112 s.save()
114 for n in new:
115 p, created = Podcast.objects.get_or_create(url=n,
116 defaults={'title':n,'description':n,'last_update':datetime.now()})
117 s = SubscriptionAction(podcast=p, action=SUBSCRIBE_ACTION, device=d)
118 s.save()
120 # Only an empty response is a successful response
121 return HttpResponse('', mimetype='text/plain')