Merge pull request #793 from gpodder/remove-advertise
[mygpo.git] / mygpo / subscriptions / views.py
blobe1b6d63fb6ce50306a5d75dfe2be736bedcfafdf
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 gettext 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 (
22 get_subscribed_podcasts,
23 get_subscription_change_history,
24 get_subscription_history,
26 from mygpo.web.utils import get_podcast_link_target
27 from mygpo.utils import parse_bool
28 from mygpo.decorators import requires_token
29 from mygpo.web.utils import symbian_opml_changes
32 @vary_on_cookie
33 @cache_control(private=True)
34 @login_required
35 def show_list(request):
36 current_site = RequestSite(request)
37 subscriptionlist = create_subscriptionlist(request)
38 return render(
39 request,
40 "subscriptions.html",
42 "subscriptionlist": subscriptionlist,
43 "url": current_site,
44 "podcast_ad": Podcast.objects.get_advertised_podcast(),
49 @vary_on_cookie
50 @cache_control(private=True)
51 @login_required
52 def download_all(request):
53 podcasts = get_subscribed_podcasts(request.user)
54 response = simple.format_podcast_list(podcasts, "opml", request.user.username)
55 response["Content-Disposition"] = "attachment; filename=all-subscriptions.opml"
56 return response
59 def create_subscriptionlist(request):
60 user = request.user
62 # get all non-deleted subscriptions
63 subscriptions = (
64 Subscription.objects.filter(user=user)
65 .exclude(deleted=True)
66 .select_related("podcast", "client")
67 .prefetch_related("podcast__slugs")
70 # grou clients by subscribed podcasts
71 subscription_list = {}
72 for subscription in subscriptions:
73 podcast = subscription.podcast
75 if not podcast in subscription_list:
76 subscription_list[podcast] = {
77 "podcast": podcast,
78 "devices": [],
79 "episodes": podcast.episode_count,
82 subscription_list[podcast]["devices"].append(subscription.client)
84 # sort most recently updated podcast first
85 subscriptions = subscription_list.values()
86 now = datetime.utcnow()
87 sort_key = lambda s: s["podcast"].latest_episode_timestamp or now
88 subscriptions = sorted(subscriptions, key=sort_key, reverse=True)
89 return subscriptions
92 @requires_token(token_name="subscriptions_token")
93 def subscriptions_feed(request, username):
94 # Create to feed manually so we can wrap the token-authentication around it
95 f = SubscriptionsFeed(username)
96 obj = f.get_object(request, username)
97 feedgen = f.get_feed(obj, request)
98 response = HttpResponse(content_type=feedgen.content_type)
99 feedgen.write(response, "utf-8")
100 return response
103 class SubscriptionsFeed(Feed):
104 """A feed showing subscription changes for a certain user"""
106 NUM_ITEMS = 20
108 def __init__(self, username):
109 self.username = username
111 def get_object(self, request, username):
112 self.site = RequestSite(request)
113 User = get_user_model()
114 user = get_object_or_404(User, username=username)
115 return user
117 def title(self, user):
118 return _("%(username)s's Podcast Subscriptions on %(site)s") % dict(
119 username=user.username, site=self.site
122 def description(self, user):
123 return _(
124 "Recent changes to %(username)s's podcast subscriptions on %(site)s"
125 ) % dict(username=user.username, site=self.site)
127 def link(self, user):
128 return reverse("shared-subscriptions", args=[user.username])
130 def items(self, user):
131 history = get_subscription_history(user, public_only=True)
132 history = get_subscription_change_history(history)
133 history = list(history)[-self.NUM_ITEMS :]
134 return history
136 def author_name(self, user):
137 return user.username
139 def author_link(self, user):
140 return reverse("shared-subscriptions", args=[user.username])
142 # entry-specific data below
144 description_template = "subscription-feed-description.html"
146 def item_title(self, entry):
147 if entry.action == "subscribe":
148 s = _("%(username)s subscribed to %(podcast)s (%(site)s)")
149 else:
150 s = _("%(username)s unsubscribed from %(podcast)s (%(site)s)")
152 return s % dict(
153 username=self.username, podcast=entry.podcast.display_title, site=self.site
156 def item_link(self, item):
157 return get_podcast_link_target(item.podcast)
159 def item_pubdate(self, item):
160 return item.timestamp
163 @requires_token(
164 token_name="subscriptions_token", denied_template="user_subscriptions_denied.html"
166 def for_user(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)
170 token = user.profile.get_token("subscriptions_token")
172 return render(
173 request,
174 "user_subscriptions.html",
175 {"subscriptions": subscriptions, "other_user": user, "token": token},
179 @requires_token(token_name="subscriptions_token")
180 def for_user_opml(request, username):
181 User = get_user_model()
182 user = get_object_or_404(User, username=username)
183 subscriptions = get_subscribed_podcasts(user, only_public=True)
185 if parse_bool(request.GET.get("symbian", False)):
186 subscriptions = map(symbian_opml_changes, [p.podcast for p in subscriptions])
188 response = render(
189 request,
190 "user_subscriptions.opml",
191 {"subscriptions": subscriptions, "other_user": user},
193 response["Content-Disposition"] = (
194 "attachment; filename=%s-subscriptions.opml" % username
196 return response