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'
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
)
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
]
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
]
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
))
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
))
82 p
, created
= Podcast
.objects
.get_or_create(url
=r
)
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')
92 emailaddr
= request
.GET
.get('username', None)
93 password
= request
.GET
.get('password', None)
95 user
= auth(emailaddr
, password
)
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:
120 user
= User
.objects
.get(email__exact
=emailaddr
)
121 except User
.DoesNotExist
:
124 if not user
.check_password(password
):
127 if not user
.is_active
: