1 from datetime
import datetime
3 from django
.core
.urlresolvers
import reverse
4 from django
.contrib
.auth
.decorators
import login_required
5 from django
.contrib
.sites
.models
import RequestSite
6 from django
.shortcuts
import render
7 from django
.contrib
.syndication
.views
import Feed
8 from django
.utils
.translation
import ugettext
as _
9 from django
.http
import HttpResponse
, Http404
10 from django
.views
.decorators
.vary
import vary_on_cookie
11 from django
.views
.decorators
.cache
import cache_control
13 from mygpo
.podcasts
.models
import Podcast
14 from mygpo
.utils
import parse_bool
, unzip
, skip_pairs
15 from mygpo
.decorators
import requires_token
16 from mygpo
.api
import simple
17 from mygpo
.users
.models
import HistoryEntry
, User
18 from mygpo
.users
.subscriptions
import get_subscribed_podcasts
19 from mygpo
.web
.utils
import symbian_opml_changes
, get_podcast_link_target
20 from mygpo
.db
.couchdb
.podcast_state
import subscriptions_by_user
24 @cache_control(private
=True)
26 def show_list(request
):
27 current_site
= RequestSite(request
)
28 subscriptionlist
= create_subscriptionlist(request
)
29 return render(request
, 'subscriptions.html', {
30 'subscriptionlist': subscriptionlist
,
36 @cache_control(private
=True)
38 def download_all(request
):
39 podcasts
= get_subscribed_podcasts(request
.user
)
40 response
= simple
.format_podcast_list(podcasts
, 'opml', request
.user
.username
)
41 response
['Content-Disposition'] = 'attachment; filename=all-subscriptions.opml'
45 @requires_token(token_name
='subscriptions_token', denied_template
='user_subscriptions_denied.html')
46 def for_user(request
, username
):
47 user
= User
.get_user(username
)
51 subscriptions
= user
.get_subscribed_podcasts(public
=True)
52 token
= user
.profile
.get_token('subscriptions_token')
54 return render(request
, 'user_subscriptions.html', {
55 'subscriptions': subscriptions
,
60 @requires_token(token_name
='subscriptions_token')
61 def for_user_opml(request
, username
):
62 user
= User
.get_user(username
)
66 subscriptions
= user
.get_subscribed_podcasts(public
=True)
68 if parse_bool(request
.GET
.get('symbian', False)):
69 subscriptions
= map(symbian_opml_changes
, subscriptions
)
71 response
= render(request
, 'user_subscriptions.opml', {
72 'subscriptions': subscriptions
,
75 response
['Content-Disposition'] = 'attachment; filename=%s-subscriptions.opml' % username
79 def create_subscriptionlist(request
):
81 subscriptions
= subscriptions_by_user(user
)
86 # Load all Podcasts and Devices first to ensure that they are
87 # only loaded once, not for each occurance in a subscription
88 public
, podcast_ids
, device_ids
= unzip(subscriptions
)
89 podcast_ids
= list(set(podcast_ids
))
90 device_ids
= list(set(device_ids
))
92 podcasts
= Podcast
.objects
.filter(id__in
=podcast_ids
)
93 podcasts
= {podcast
.id.hex: podcast
for podcast
in podcasts
}
94 devices
= {client
.id.hex: client
for client
in user
.client_set
.all()}
96 subscription_list
= {}
97 for public
, podcast_id
, device_id
in subscriptions
:
98 device
= devices
.get(device_id
)
99 if not podcast_id
in subscription_list
:
100 podcast
= podcasts
.get(podcast_id
, None)
104 subscription_list
[podcast_id
] = {
105 'podcast': podcasts
[podcast_id
],
106 'devices': [device
] if device
else [],
107 'episodes': podcast
.episode_count
,
111 subscription_list
[podcast_id
]['devices'].append(device
)
113 subscriptions
= subscription_list
.values()
114 sort_key
= lambda s
: s
['podcast'].latest_episode_timestamp
or datetime
.utcnow()
115 subscriptions
= sorted(subscriptions
, key
=sort_key
, reverse
=True)
119 @requires_token(token_name
='subscriptions_token')
120 def subscriptions_feed(request
, username
):
121 # Create to feed manually so we can wrap the token-authentication around it
122 f
= SubscriptionsFeed(username
)
123 obj
= f
.get_object(request
, username
)
124 feedgen
= f
.get_feed(obj
, request
)
125 response
= HttpResponse(content_type
=feedgen
.mime_type
)
126 feedgen
.write(response
, 'utf-8')
130 class SubscriptionsFeed(Feed
):
131 """ A feed showing subscription changes for a certain user """
133 def __init__(self
, username
):
134 self
.username
= username
136 def get_object(self
, request
, username
):
137 self
.site
= RequestSite(request
)
138 return User
.get_user(username
)
140 def title(self
, user
):
141 return _('%(username)s\'s Podcast Subscriptions on %(site)s') % \
142 dict(username
=user
.username
, site
=self
.site
)
144 def description(self
, user
):
145 return _('Recent changes to %(username)s\'s podcast subscriptions on %(site)s') % \
146 dict(username
=user
.username
, site
=self
.site
)
148 def link(self
, user
):
149 return reverse('shared-subscriptions', args
=[user
.username
])
151 def items(self
, user
):
153 history
= user
.get_global_subscription_history(public
=True)
154 history
= skip_pairs(history
)
155 history
= list(history
)[-NUM_ITEMS
:]
156 history
= HistoryEntry
.fetch_data(user
, history
)
157 history
= filter(lambda e
:e
.podcast
, history
)
160 def author_name(self
, user
):
163 def author_link(self
, user
):
164 return reverse('shared-subscriptions', args
=[user
.username
])
166 # entry-specific data below
168 description_template
= "subscription-feed-description.html"
170 def item_title(self
, entry
):
171 if entry
.action
== 'subscribe':
172 s
= _('%(username)s subscribed to %(podcast)s (%(site)s)')
174 s
= _('%(username)s unsubscribed from %(podcast)s (%(site)s)')
176 return s
% dict(username
=self
.username
,
177 podcast
=entry
.podcast
.display_title
,
180 def item_link(self
, item
):
181 return get_podcast_link_target(item
.podcast
)
183 def item_pubdate(self
, item
):
184 return item
.timestamp