simplify, refactor APIs
[mygpo.git] / mygpo / api / legacy.py
blobb18981371ec0de1fd80c4ce075adff4ddff8fbf0
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 django.http import HttpResponse
19 from django.contrib.auth.models import User
20 from mygpo.api.opml import Importer, Exporter
21 from mygpo.api.models import Subscription, Podcast, Device
22 from mygpo.api.backend import get_device
23 from datetime import datetime
24 from django.utils.datastructures import MultiValueDictKeyError
25 from django.db import IntegrityError
26 from mygpo.log import log
27 from mygpo.api.sanitizing import sanitize_url
28 from django.views.decorators.csrf import csrf_exempt
30 LEGACY_DEVICE_NAME = 'Legacy Device'
31 LEGACY_DEVICE_UID = 'legacy'
33 @csrf_exempt
34 def upload(request):
35 try:
36 emailaddr = request.POST['username']
37 password = request.POST['password']
38 action = request.POST['action']
39 protocol = request.POST['protocol']
40 opml = request.FILES['opml'].read()
41 except MultiValueDictKeyError:
42 return HttpResponse("@PROTOERROR", mimetype='text/plain')
44 user = auth(emailaddr, password)
45 if (not user):
46 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
48 d = get_device(user, LEGACY_DEVICE_UID)
50 existing = Subscription.objects.filter(user=user, device=d)
52 existing_urls = [e.podcast.url for e in existing]
54 i = Importer(opml)
56 podcast_urls = [p['url'] for p in i.items]
57 podcast_urls = map(sanitize_url, podcast_urls)
58 podcast_urls = filter(lambda x: x, podcast_urls)
60 new = [u for u in podcast_urls if u not in existing_urls]
61 rem = [e.podcast.url for e in existing if e.podcast.url not in podcast_urls]
63 #remove duplicates
64 new = list(set(new))
65 rem = list(set(rem))
67 for n in new:
68 try:
69 p, created = Podcast.objects.get_or_create(url=n)
70 except IntegrityError, e:
71 log('/upload: Error trying to get podcast object: %s (error: %s)' % (n, e))
72 continue
74 try:
75 p.subscribe(d)
76 except IntegrityError, e:
77 log('/upload: error while adding subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
78 except ValueError, ve:
79 log('/upload: error while adding subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
81 for r in rem:
82 p, created = Podcast.objects.get_or_create(url=r)
83 try:
84 p.unsubscribe(d)
85 except IntegrityError, e:
86 log('/upload: error while removing subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
88 return HttpResponse('@SUCCESS', mimetype='text/plain')
90 @csrf_exempt
91 def getlist(request):
92 emailaddr = request.GET.get('username', None)
93 password = request.GET.get('password', None)
95 user = auth(emailaddr, password)
96 if user is None:
97 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
99 d, created = Device.objects.get_or_create(user=user, uid=LEGACY_DEVICE_UID,
100 defaults = {'type': 'unknown', 'name': LEGACY_DEVICE_NAME})
102 # We ignore deleted devices, because the Legacy API doesn't know such a concept
104 podcasts = [s.podcast for s in d.get_subscriptions()]
106 # FIXME: Get username and set a proper title (e.g. "thp's subscription list")
107 title = 'Your subscription list'
108 exporter = Exporter(title)
110 opml = exporter.generate(podcasts)
112 return HttpResponse(opml, mimetype='text/xml')
115 def auth(emailaddr, password):
116 if emailaddr is None or password is None:
117 return None
119 try:
120 user = User.objects.get(email__exact=emailaddr)
121 except User.DoesNotExist:
122 return None
124 if not user.check_password(password):
125 return None
127 if not user.is_active:
128 return None
130 return user