1 from functools
import wraps
2 import urllib
.request
, urllib
.parse
, urllib
.error
4 from django
.shortcuts
import render
5 from django
.http
import HttpResponse
, HttpResponseRedirect
, \
6 HttpResponseForbidden
, Http404
7 from django
.core
.cache
import cache
8 from django
.views
.decorators
.cache
import never_cache
, cache_control
9 from django
.views
.decorators
.vary
import vary_on_cookie
10 from django
.urls
import reverse
11 from django
.utils
.translation
import ugettext
as _
12 from django
.contrib
import messages
13 from django
.contrib
.auth
import get_user_model
14 from django
.contrib
.contenttypes
.models
import ContentType
15 from django
.shortcuts
import get_object_or_404
17 from mygpo
.podcasts
.models
import PodcastGroup
, Podcast
, Episode
18 from mygpo
.publisher
.auth
import require_publisher
, is_publisher
19 from mygpo
.publisher
.forms
import SearchPodcastForm
20 from mygpo
.publisher
.utils
import listener_data
, episode_listener_data
, \
21 check_publisher_permission
, subscriber_data
22 from mygpo
.podcasts
.views
.episode
import (
23 slug_decorator
as episode_slug_decorator
,
24 id_decorator
as episode_id_decorator
26 from mygpo
.podcasts
.views
.podcast
import (
27 slug_decorator
as podcast_slug_decorator
,
28 id_decorator
as podcast_id_decorator
30 from mygpo
.web
.utils
import get_podcast_link_target
, normalize_twitter
, \
31 get_episode_link_target
32 from django
.contrib
.sites
.requests
import RequestSite
33 from mygpo
.data
.tasks
import update_podcasts
34 from mygpo
.data
.models
import PodcastUpdateResult
35 from mygpo
.decorators
import requires_token
, allowed_methods
36 from mygpo
.pubsub
.models
import HubSubscription
40 @cache_control(private
=True)
42 if is_publisher(request
.user
):
43 podcasts
= Podcast
.objects
.filter(publishedpodcast__publisher
=request
.user
)\
44 .prefetch_related('slugs')
45 site
= RequestSite(request
)
46 update_token
= request
.user
.profile
.get_token('publisher_update_token')
47 form
= SearchPodcastForm()
48 return render(request
, 'publisher/home.html', {
49 'update_token': update_token
,
56 site
= RequestSite(request
)
57 return render(request
, 'publisher/info.html', {
63 @cache_control(private
=True)
65 def search_podcast(request
):
66 form
= SearchPodcastForm(request
.POST
)
68 podcast_url
= form
.cleaned_data
['url']
69 podcast
= get_object_or_404(Podcast
, urls__url
=podcast_url
)
70 url
= get_podcast_link_target(podcast
, 'podcast-publisher-detail')
72 url
= reverse('publisher')
74 return HttpResponseRedirect(url
)
78 @cache_control(private
=True)
80 @allowed_methods(['GET', 'POST'])
81 def podcast(request
, podcast
):
83 if not check_publisher_permission(request
.user
, podcast
):
84 return HttpResponseForbidden()
86 timeline_data
= listener_data([podcast
])
87 subscription_data
= subscriber_data([podcast
])[-20:]
89 update_token
= request
.user
.profile
.get_token('publisher_update_token')
92 pubsubscription
= HubSubscription
.objects
.get(topic_url
=podcast
.url
)
93 except HubSubscription
.DoesNotExist
:
94 pubsubscription
= None
98 update_results
= PodcastUpdateResult
.objects
.filter(podcast
=podcast
)
99 update_results
= update_results
[:MAX_UPDATE_RESULTS
]
101 site
= RequestSite(request
)
102 feedurl_quoted
= urllib
.parse
.quote(podcast
.url
.encode('ascii'))
104 return render(request
, 'publisher/podcast.html', {
107 'group': podcast
.group
,
109 'timeline_data': timeline_data
,
110 'subscriber_data': subscription_data
,
111 'update_token': update_token
,
112 'feedurl_quoted': feedurl_quoted
,
113 'pubsubscription': pubsubscription
,
114 'update_results': update_results
,
119 @cache_control(private
=True)
121 def group(request
, group
):
123 podcasts
= group
.podcasts
125 # users need to have publisher access for at least one of the group's podcasts
126 if not any([check_publisher_permission(request
.user
, p
) for p
in podcasts
]):
127 return HttpResponseForbidden()
129 timeline_data
= listener_data(podcasts
)
130 subscription_data
= list(subscriber_data(podcasts
))[-20:]
132 return render(request
, 'publisher/group.html', {
134 'timeline_data': timeline_data
,
135 'subscriber_data': subscription_data
,
140 @cache_control(private
=True)
142 def update_podcast(request
, podcast
):
144 if not check_publisher_permission(request
.user
, podcast
):
145 return HttpResponseForbidden()
147 update_podcasts
.delay([podcast
.url
])
148 messages
.success(request
, _('The update has been scheduled. It might take some time until the results are visible.'))
150 url
= get_podcast_link_target(podcast
, 'podcast-publisher-detail')
151 return HttpResponseRedirect(url
)
155 @cache_control(private
=True)
157 def save_podcast(request
, podcast
):
158 twitter
= normalize_twitter(request
.POST
.get('twitter', ''))
159 podcast
.twitter
= twitter
161 messages
.success(request
, _('Data updated'))
162 url
= get_podcast_link_target(podcast
, 'podcast-publisher-detail')
163 return HttpResponseRedirect(url
)
169 def new_update_token(request
, username
):
170 request
.user
.profile
.create_new_token('publisher_update_token')
171 request
.user
.profile
.save()
172 messages
.success(request
, _('Publisher token updated'))
173 return HttpResponseRedirect(reverse('publisher'))
177 @requires_token(token_name
='publisher_update_token')
178 def update_published_podcasts(request
, username
):
179 User
= get_user_model()
180 user
= get_object_or_404(User
, username
=username
)
181 published_podcasts
= [pp
.podcast
for pp
in user
.publishedpodcast_set
.all()]
182 update_podcasts
.delay([podcast
.url
for podcast
in published_podcasts
])
183 return HttpResponse('Updated:\n' + '\n'.join([p
.url
for p
in published_podcasts
]), content_type
='text/plain')
187 @cache_control(private
=True)
189 def episodes(request
, podcast
):
191 if not check_publisher_permission(request
.user
, podcast
):
192 return HttpResponseForbidden()
194 episodes
= Episode
.objects
.filter(podcast
=podcast
).select_related('podcast').prefetch_related('slugs', 'podcast__slugs')
196 listeners
= filter(None, (e
.listeners
for e
in episodes
))
197 max_listeners
= max(listeners
, default
=0)
199 return render(request
, 'publisher/episodes.html', {
201 'episodes': episodes
,
202 'max_listeners': max_listeners
208 @cache_control(private
=True)
209 @allowed_methods(['GET', 'POST'])
210 def episode(request
, episode
):
212 site
= RequestSite(request
)
213 podcast
= episode
.podcast
215 if not check_publisher_permission(request
.user
, podcast
):
216 return HttpResponseForbidden()
218 if request
.method
== 'POST':
219 form
= None # EpisodeForm(request.POST, instance=e)
220 # if form.is_valid():
223 elif request
.method
== 'GET':
224 form
= None # EpisodeForm(instance=e)
226 timeline_data
= list(episode_listener_data(episode
))
228 return render(request
, 'publisher/episode.html', {
229 'is_secure': request
.is_secure(),
230 'domain': site
.domain
,
234 'timeline_data': timeline_data
,
240 @allowed_methods(['POST'])
241 def update_episode_slug(request
, episode
):
242 """ sets a new "main" slug, and moves the existing to the merged slugs """
244 new_slug
= request
.POST
.get('slug')
245 podcast
= episode
.podcast
248 # remove the new slug from other episodes (of the same podcast)
249 other_episodes
= Episode
.objects
.filter(
251 slugs__slug
=new_slug
,
252 slugs__content_type
=ContentType
.objects
.get_for_model(Episode
),
255 for other_episode
in other_episodes
:
257 if other_episode
== episode
:
260 other_episode
.remove_slug(new_slug
)
261 messages
.warning(request
,
262 _('Removed slug {slug} from {episode}'.format(
263 slug
=new_slug
, episode
=other_episode
.title
))
266 episode
.set_slug(new_slug
)
268 # TODO: we should use better cache invalidation
271 return HttpResponseRedirect(
272 get_episode_link_target(episode
, podcast
, 'episode-publisher-detail')
277 @cache_control(private
=True)
279 current_site
= RequestSite(request
)
280 return render(request
, 'link.html', {
286 @cache_control(private
=True)
287 def advertise(request
):
288 site
= RequestSite(request
)
289 return render(request
, 'publisher/advertise.html', {
294 def group_id_decorator(f
):
296 def _decorator(request
, pg_slug
, *args
, **kwargs
):
297 group
= get_object_or_404(PodcastGroup
, pk
=slug_id
)
298 return f(request
, group
, *args
, **kwargs
)
303 episode_slug
= episode_slug_decorator(episode
)
304 update_episode_slug_slug
= episode_slug_decorator(update_episode_slug
)
305 podcast_slug
= podcast_slug_decorator(podcast
)
306 episodes_slug
= podcast_slug_decorator(episodes
)
307 update_podcast_slug
= podcast_slug_decorator(update_podcast
)
308 save_podcast_slug
= podcast_slug_decorator(save_podcast
)
310 episode_id
= episode_id_decorator(episode
)
311 update_episode_slug_id
= episode_id_decorator(update_episode_slug
)
312 podcast_id
= podcast_id_decorator(podcast
)
313 episodes_id
= podcast_id_decorator(episodes
)
314 update_podcast_id
= podcast_id_decorator(update_podcast
)
315 save_podcast_id
= podcast_id_decorator(save_podcast
)
317 group_slug
= group_id_decorator(group
)
318 group_id
= group_id_decorator(group
)