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'
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
)
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
55 existing
= Subscription
.objects
.filter(user
=user
, device
=d
)
57 existing_urls
= [e
.podcast
.url
for e
in existing
]
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
]
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
))
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
))
87 p
, created
= Podcast
.objects
.get_or_create(url
=r
)
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')
97 emailaddr
= request
.GET
.get('username', None)
98 password
= request
.GET
.get('password', None)
100 user
= auth(emailaddr
, password
)
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:
124 user
= User
.objects
.get(email__exact
=emailaddr
)
125 except User
.DoesNotExist
:
128 if not user
.check_password(password
):
131 if not user
.is_active
: