1 from datetime
import datetime
3 from django
.urls
import reverse
4 from django
.contrib
.auth
.decorators
import login_required
5 from django
.contrib
.sites
.requests
import RequestSite
6 from django
.shortcuts
import render
, get_object_or_404
7 from django
.http
import HttpResponse
8 from django
.views
.decorators
.vary
import vary_on_cookie
9 from django
.views
.decorators
.cache
import cache_control
10 from django
.utils
.translation
import ugettext
as _
11 from django
.contrib
.syndication
.views
import Feed
12 from django
.contrib
.auth
import get_user_model
14 from mygpo
.podcasts
.models
import Podcast
15 from mygpo
.subscriptions
.models
import Subscription
16 from mygpo
.users
.settings
import PUBLIC_SUB_PODCAST
17 from mygpo
.api
import simple
18 from mygpo
.subscriptions
import get_subscribed_podcasts
19 from mygpo
.decorators
import requires_token
20 from mygpo
.users
.models
import HistoryEntry
21 from mygpo
.subscriptions
import (get_subscribed_podcasts
,
22 get_subscription_change_history
, get_subscription_history
)
23 from mygpo
.web
.utils
import get_podcast_link_target
24 from mygpo
.utils
import parse_bool
25 from mygpo
.decorators
import requires_token
26 from mygpo
.web
.utils
import symbian_opml_changes
31 @cache_control(private
=True)
33 def show_list(request
):
34 current_site
= RequestSite(request
)
35 subscriptionlist
= create_subscriptionlist(request
)
36 return render(request
, 'subscriptions.html', {
37 'subscriptionlist': subscriptionlist
,
39 'podcast_ad': Podcast
.objects
.get_advertised_podcast(),
43 @cache_control(private
=True)
45 def download_all(request
):
46 podcasts
= get_subscribed_podcasts(request
.user
)
47 response
= simple
.format_podcast_list(podcasts
, 'opml', request
.user
.username
)
48 response
['Content-Disposition'] = 'attachment; filename=all-subscriptions.opml'
52 def create_subscriptionlist(request
):
55 # get all non-deleted subscriptions
56 subscriptions
= Subscription
.objects
.filter(user
=user
)\
57 .exclude(deleted
=True)\
58 .select_related('podcast', 'client')
60 # grou clients by subscribed podcasts
61 subscription_list
= {}
62 for subscription
in subscriptions
:
63 podcast
= subscription
.podcast
65 if not podcast
in subscription_list
:
66 subscription_list
[podcast
] = {
69 'episodes': podcast
.episode_count
,
72 subscription_list
[podcast
]['devices'].append(subscription
.client
)
74 # sort most recently updated podcast first
75 subscriptions
= subscription_list
.values()
76 now
= datetime
.utcnow()
77 sort_key
= lambda s
: s
['podcast'].latest_episode_timestamp
or now
78 subscriptions
= sorted(subscriptions
, key
=sort_key
, reverse
=True)
82 @requires_token(token_name
='subscriptions_token')
83 def subscriptions_feed(request
, username
):
84 # Create to feed manually so we can wrap the token-authentication around it
85 f
= SubscriptionsFeed(username
)
86 obj
= f
.get_object(request
, username
)
87 feedgen
= f
.get_feed(obj
, request
)
88 response
= HttpResponse(content_type
=feedgen
.content_type
)
89 feedgen
.write(response
, 'utf-8')
93 class SubscriptionsFeed(Feed
):
94 """ A feed showing subscription changes for a certain user """
98 def __init__(self
, username
):
99 self
.username
= username
101 def get_object(self
, request
, username
):
102 self
.site
= RequestSite(request
)
103 User
= get_user_model()
104 user
= get_object_or_404(User
, username
=username
)
107 def title(self
, user
):
108 return _('%(username)s\'s Podcast Subscriptions on %(site)s') % \
109 dict(username
=user
.username
, site
=self
.site
)
111 def description(self
, user
):
112 return _('Recent changes to %(username)s\'s podcast subscriptions on %(site)s') % \
113 dict(username
=user
.username
, site
=self
.site
)
115 def link(self
, user
):
116 return reverse('shared-subscriptions', args
=[user
.username
])
118 def items(self
, user
):
119 history
= get_subscription_history(user
, public_only
=True)
120 history
= get_subscription_change_history(history
)
121 history
= list(history
)[-self
.NUM_ITEMS
:]
124 def author_name(self
, user
):
127 def author_link(self
, user
):
128 return reverse('shared-subscriptions', args
=[user
.username
])
130 # entry-specific data below
132 description_template
= "subscription-feed-description.html"
134 def item_title(self
, entry
):
135 if entry
.action
== 'subscribe':
136 s
= _('%(username)s subscribed to %(podcast)s (%(site)s)')
138 s
= _('%(username)s unsubscribed from %(podcast)s (%(site)s)')
140 return s
% dict(username
=self
.username
,
141 podcast
=entry
.podcast
.display_title
,
144 def item_link(self
, item
):
145 return get_podcast_link_target(item
.podcast
)
147 def item_pubdate(self
, item
):
148 return item
.timestamp
152 @requires_token(token_name
='subscriptions_token', denied_template
='user_subscriptions_denied.html')
153 def for_user(request
, username
):
154 User
= get_user_model()
155 user
= get_object_or_404(User
, username
=username
)
156 subscriptions
= get_subscribed_podcasts(user
, only_public
=True)
157 token
= user
.profile
.get_token('subscriptions_token')
159 return render(request
, 'user_subscriptions.html', {
160 'subscriptions': subscriptions
,
165 @requires_token(token_name
='subscriptions_token')
166 def for_user_opml(request
, username
):
167 User
= get_user_model()
168 user
= get_object_or_404(User
, username
=username
)
169 subscriptions
= get_subscribed_podcasts(user
, only_public
=True)
171 if parse_bool(request
.GET
.get('symbian', False)):
172 subscriptions
= map(symbian_opml_changes
,
173 [p
.podcast
for p
in subscriptions
])
175 response
= render(request
, 'user_subscriptions.opml', {
176 'subscriptions': subscriptions
,
179 response
['Content-Disposition'] = 'attachment; filename=%s-subscriptions.opml' % username