1 from itertools
import imap
as map
4 from django
.http
import HttpResponseNotFound
, Http404
, HttpResponseRedirect
5 from django
.core
.urlresolvers
import reverse
6 from django
.shortcuts
import render
7 from django
.contrib
.sites
.models
import RequestSite
8 from django
.views
.decorators
.cache
import cache_control
9 from django
.views
.decorators
.vary
import vary_on_cookie
10 from django
.utils
.decorators
import method_decorator
11 from django
.views
.generic
.base
import View
12 from django
.contrib
.auth
.decorators
import login_required
13 from django
.contrib
import messages
14 from django
.utils
.translation
import ugettext
as _
16 from feedservice
.parse
.models
import ParserException
17 from feedservice
.parse
import FetchFeedException
19 from mygpo
.core
.proxy
import proxy_object
20 from mygpo
.directory
.toplist
import PodcastToplist
, EpisodeToplist
, \
22 from mygpo
.directory
.search
import search_podcasts
23 from mygpo
.web
.utils
import process_lang_params
, get_language_names
, \
24 get_page_list
, get_podcast_link_target
25 from mygpo
.directory
.tags
import Topics
26 from mygpo
.users
.models
import User
27 from mygpo
.data
.feeddownloader
import PodcastUpdater
, NoEpisodesException
28 from mygpo
.db
.couchdb
.podcast
import get_podcast_languages
, podcasts_by_id
, \
29 random_podcasts
, podcasts_to_dict
, podcast_for_url
30 from mygpo
.db
.couchdb
.directory
import category_for_tag
31 from mygpo
.db
.couchdb
.podcastlist
import random_podcastlists
, \
32 podcastlist_count
, podcastlists_by_rating
36 @cache_control(private
=True)
37 def toplist(request
, num
=100, lang
=None):
39 lang
= process_lang_params(request
)
41 toplist
= PodcastToplist(lang
)
42 entries
= toplist
[:num
]
44 max_subscribers
= max([p
.subscriber_count() for (oldp
, p
) in entries
]) if entries
else 0
45 current_site
= RequestSite(request
)
47 languages
= get_podcast_languages()
48 all_langs
= get_language_names(languages
)
50 return render(request
, 'toplist.html', {
52 'max_subscribers': max_subscribers
,
55 'all_languages': all_langs
,
60 """ A carousel demo """
62 @method_decorator(cache_control(private
=True))
63 @method_decorator(vary_on_cookie
)
64 def get(self
, request
):
66 return render(request
, 'carousel.html', {
67 # evaluated lazyly, cached by template
72 class Directory(View
):
73 """ The main directory page """
75 @method_decorator(cache_control(private
=True))
76 @method_decorator(vary_on_cookie
)
77 def get(self
, request
):
79 return render(request
, 'directory.html', {
81 # evaluated lazyly, cached by template
83 'trending_podcasts': TrendingPodcasts(''),
84 'podcastlists': self
.get_random_list(),
85 'random_podcasts': self
.get_random_podcast(),
89 def get_random_list(self
, podcasts_per_list
=5):
90 random_list
= next(random_podcastlists(), None)
93 random_list
= proxy_object(random_list
)
94 random_list
.more_podcasts
= max(0, len(random_list
.podcasts
) - podcasts_per_list
)
95 random_list
.podcasts
= podcasts_by_id(random_list
.podcasts
[:podcasts_per_list
])
96 random_list
.user
= User
.get(random_list
.user
)
100 def get_random_podcast(self
):
101 random_podcast
= next(random_podcasts(), None)
103 yield random_podcast
.get_podcast()
106 @cache_control(private
=True)
108 def category(request
, category
, page_size
=20):
109 category
= category_for_tag(category
)
111 return HttpResponseNotFound()
113 # Make sure page request is an int. If not, deliver first page.
115 page
= int(request
.GET
.get('page', '1'))
119 entries
= category
.get_podcasts( (page
-1) * page_size
, page
*page_size
)
120 podcasts
= filter(None, entries
)
121 num_pages
= len(category
.podcasts
) / page_size
123 page_list
= get_page_list(1, num_pages
, page
, 15)
125 return render(request
, 'category.html', {
127 'category': category
.label
,
128 'page_list': page_list
,
135 @cache_control(private
=True)
137 def search(request
, template
='search.html', args
={}):
139 if 'q' in request
.GET
:
140 q
= request
.GET
.get('q', '').encode('utf-8')
143 page
= int(request
.GET
.get('page', 1))
147 results
, total
= search_podcasts(q
=q
, skip
=RESULTS_PER_PAGE
*(page
-1))
148 num_pages
= total
/ RESULTS_PER_PAGE
150 page_list
= get_page_list(1, num_pages
, page
, 15)
157 max_subscribers
= max([p
.subscriber_count() for p
in results
] + [0])
158 current_site
= RequestSite(request
)
160 return render(request
, template
, dict(
163 page_list
= page_list
,
164 max_subscribers
= max_subscribers
,
165 domain
= current_site
.domain
,
170 @cache_control(private
=True)
172 def episode_toplist(request
, num
=100):
173 lang
= process_lang_params(request
)
175 toplist
= EpisodeToplist(language
=lang
)
176 entries
= list(map(proxy_object
, toplist
[:num
]))
178 # load podcast objects
179 podcast_ids
= [e
.podcast
for e
in entries
]
180 podcasts
= podcasts_to_dict(podcast_ids
, True)
181 for entry
in entries
:
182 entry
.podcast
= podcasts
.get(entry
.podcast
, None)
184 current_site
= RequestSite(request
)
186 # Determine maximum listener amount (or 0 if no entries exist)
187 max_listeners
= max([0]+[e
.listeners
for e
in entries
])
189 languages
= get_podcast_languages()
190 all_langs
= get_language_names(languages
)
192 return render(request
, 'episode_toplist.html', {
194 'max_listeners': max_listeners
,
197 'all_languages': all_langs
,
201 @cache_control(private
=True)
203 def podcast_lists(request
, page_size
=20):
205 # Make sure page request is an int. If not, deliver first page.
207 page
= int(request
.GET
.get('page', '1'))
211 lists
= podcastlists_by_rating(skip
=(page
-1) * page_size
, limit
=page_size
)
214 def _prepare_list(l
):
215 user
= User
.get(l
.user
)
217 l
.username
= user
.username
220 lists
= map(_prepare_list
, lists
)
222 num_pages
= int(ceil(podcastlist_count() / float(page_size
)))
224 page_list
= get_page_list(1, num_pages
, page
, 15)
226 return render(request
, 'podcast_lists.html', {
228 'page_list': page_list
,
233 class MissingPodcast(View
):
234 """ Check if a podcast is missing """
236 @method_decorator(login_required
)
237 def get(self
, request
):
239 site
= RequestSite(request
)
241 # check if we're doing a query
242 url
= request
.GET
.get('q', None)
249 podcast
= podcast_for_url(url
)
251 # if the podcast does already exist, there's nothing more to do
255 # check if we could add a podcast for the given URL
258 updater
= PodcastUpdater()
261 can_add
= updater
.verify_podcast_url(url
)
263 except (ParserException
, FetchFeedException
,
264 NoEpisodesException
) as ex
:
266 messages
.error(request
, str(ex
))
268 return render(request
, 'missing.html', {
276 class AddPodcast(View
):
277 """ Add a missing podcast"""
279 @method_decorator(login_required
)
280 @method_decorator(cache_control(private
=True))
281 @method_decorator(vary_on_cookie
)
282 def post(self
, request
):
284 url
= request
.POST
.get('url', None)
289 updater
= PodcastUpdater()
292 podcast
= updater
.update_podcast_url(url
)
294 messages
.success(request
, _('The podcast has been added'))
296 return HttpResponseRedirect(get_podcast_link_target(podcast
))
298 except (ParserException
, FetchFeedException
,
299 NoEpisodesException
) as ex
:
300 messages
.error(request
, str(ex
))
302 add_page
= '%s?q=%s' % (reverse('missing-podcast'), url
)
303 return HttpResponseRedirect(add_page
)