simplify subscribing/unsubscribing podcasts
[mygpo.git] / mygpo / api / legacy.py
blob9717f084215985737cb391e56618c19023b403a4
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 datetime import datetime
23 from django.utils.datastructures import MultiValueDictKeyError
24 from django.db import IntegrityError
25 from mygpo.log import log
26 from mygpo.api.sanitizing import sanitize_url
27 from django.views.decorators.csrf import csrf_exempt
29 LEGACY_DEVICE_NAME = 'Legacy Device'
30 LEGACY_DEVICE_UID = 'legacy'
32 @csrf_exempt
33 def upload(request):
34 try:
35 emailaddr = request.POST['username']
36 password = request.POST['password']
37 action = request.POST['action']
38 protocol = request.POST['protocol']
39 opml = request.FILES['opml'].read()
40 except MultiValueDictKeyError:
41 return HttpResponse("@PROTOERROR", mimetype='text/plain')
43 user = auth(emailaddr, password)
44 if (not user):
45 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
47 d, created = Device.objects.get_or_create(user=user, uid=LEGACY_DEVICE_UID,
48 defaults = {'type': 'unknown', 'name': LEGACY_DEVICE_NAME})
50 # undelete a previously deleted device
51 if d.deleted:
52 d.deleted = False
53 d.save()
55 existing = Subscription.objects.filter(user=user, device=d)
57 existing_urls = [e.podcast.url for e in existing]
59 i = Importer(opml)
60 podcast_urls = []
61 for p in i.items:
62 u = sanitize_url(p['url'])
63 if u != '': podcast_urls.append(u)
65 new = [u for u in podcast_urls if u not in existing_urls]
66 rem = [e.podcast.url for e in existing if e.podcast.url not in podcast_urls]
68 #remove duplicates
69 new = list(set(new))
70 rem = list(set(rem))
72 for n in new:
73 try:
74 p, created = Podcast.objects.get_or_create(url=n)
75 except IntegrityError, e:
76 log('/upload: Error trying to get podcast object: %s (error: %s)' % (n, e))
77 continue
79 try:
80 p.subscribe(d)
81 except IntegrityError, e:
82 log('/upload: error while adding subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
83 except ValueError, ve:
84 log('/upload: error while adding subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
86 for r in rem:
87 p, created = Podcast.objects.get_or_create(url=r)
88 try:
89 p.unsubscribe(d)
90 except IntegrityError, e:
91 log('/upload: error while removing subscription: user: %s, podcast: %s, error: %s' % (user.id, p.id, e))
93 return HttpResponse('@SUCCESS', mimetype='text/plain')
95 @csrf_exempt
96 def getlist(request):
97 emailaddr = request.GET.get('username', None)
98 password = request.GET.get('password', None)
100 user = auth(emailaddr, password)
101 if user is None:
102 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
104 d, created = Device.objects.get_or_create(user=user, uid=LEGACY_DEVICE_UID,
105 defaults = {'type': 'unknown', 'name': LEGACY_DEVICE_NAME})
107 # We ignore deleted devices, because the Legacy API doesn't know such a concept
109 podcasts = [s.podcast for s in d.get_subscriptions()]
111 # FIXME: Get username and set a proper title (e.g. "thp's subscription list")
112 title = 'Your subscription list'
113 exporter = Exporter(title)
115 opml = exporter.generate(podcasts)
117 return HttpResponse(opml, mimetype='text/xml')
119 def auth(emailaddr, password):
120 if emailaddr is None or password is None:
121 return None
123 try:
124 user = User.objects.get(email__exact=emailaddr)
125 except User.DoesNotExist:
126 return None
128 if not user.check_password(password):
129 return None
131 if not user.is_active:
132 return None
134 return user