replace sanitizing rules with gPodder's normalize_feed_url()
[mygpo.git] / mygpo / api / legacy.py
blobb70e968f83028d6ce4da22d90b0feeb2cbe7e234
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 datetime import datetime
20 from django.http import HttpResponse
21 from django.utils.datastructures import MultiValueDictKeyError
22 from django.views.decorators.csrf import csrf_exempt
23 from django.views.decorators.cache import never_cache
25 from mygpo.users.models import User
26 from mygpo.api.opml import Importer, Exporter
27 from mygpo.core.models import Podcast, SubscriptionException
28 from mygpo.api.backend import get_device
29 from mygpo.db.couchdb.podcast import podcast_for_url
30 from mygpo.utils import normalize_feed_url
32 import logging
33 logger = logging.getLogger(__name__)
36 LEGACY_DEVICE_NAME = 'Legacy Device'
37 LEGACY_DEVICE_UID = 'legacy'
39 @never_cache
40 @csrf_exempt
41 def upload(request):
42 try:
43 emailaddr = request.POST['username']
44 password = request.POST['password']
45 action = request.POST['action']
46 protocol = request.POST['protocol']
47 opml = request.FILES['opml'].read()
48 except MultiValueDictKeyError:
49 return HttpResponse("@PROTOERROR", mimetype='text/plain')
51 user = auth(emailaddr, password)
52 if (not user):
53 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
55 dev = get_device(user, LEGACY_DEVICE_UID,
56 request.META.get('HTTP_USER_AGENT', ''))
58 existing_urls = [x.url for x in dev.get_subscribed_podcasts()]
60 i = Importer(opml)
62 podcast_urls = [p['url'] for p in i.items]
63 podcast_urls = map(normalize_feed_url, podcast_urls)
64 podcast_urls = filter(None, podcast_urls)
66 new = [u for u in podcast_urls if u not in existing_urls]
67 rem = [u for e in existing_urls if u not in podcast_urls]
69 #remove duplicates
70 new = list(set(new))
71 rem = list(set(rem))
73 for n in new:
74 p = podcast_for_url(n, create=True)
76 try:
77 p.subscribe(user, dev)
78 except SubscriptionException as e:
79 logger.exception('Legacy API: %(username)s: could not subscribe to podcast %(podcast_url)s on device %(device_id)s' %
80 {'username': user.username, 'podcast_url': p.url, 'device_id': dev.id})
82 for r in rem:
83 p = podcast_for_url(r, create=True)
84 try:
85 p.unsubscribe(user, dev)
86 except SubscriptionException as e:
87 logger.exception('Legacy API: %(username): could not unsubscribe from podcast %(podcast_url) on device %(device_id)' %
88 {'username': user.username, 'podcast_url': p.url, 'device_id': dev.id})
90 return HttpResponse('@SUCCESS', mimetype='text/plain')
92 @never_cache
93 @csrf_exempt
94 def getlist(request):
95 emailaddr = request.GET.get('username', None)
96 password = request.GET.get('password', None)
98 user = auth(emailaddr, password)
99 if user is None:
100 return HttpResponse('@AUTHFAIL', mimetype='text/plain')
102 dev = get_device(user, LEGACY_DEVICE_UID,
103 request.META.get('HTTP_USER_AGENT', ''),
104 undelete=True)
105 podcasts = dev.get_subscribed_podcasts()
107 title = "{username}'s subscriptions".format(username=user.username)
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 user = User.get_user_by_email(emailaddr)
120 if not user:
121 return None
123 if not user.check_password(password):
124 return None
126 if not user.is_active:
127 return None
129 return user