forked from mediadrop/mediadrop
/
podcasts.py
142 lines (114 loc) · 4.87 KB
/
podcasts.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# This file is a part of MediaDrop (http://www.mediadrop.net),
# Copyright 2009-2015 MediaDrop contributors
# For the exact contribution history, see the git revision log.
# The source code contained in this file is licensed under the GPLv3 or
# (at your option) any later version.
# See LICENSE.txt in the main project directory, for more information.
from pylons import request, response
from sqlalchemy import orm
from mediadrop.lib.auth.util import viewable_media
from mediadrop.lib import helpers
from mediadrop.lib.base import BaseController
from mediadrop.lib.decorators import (beaker_cache, expose, observable,
paginate, validate)
from mediadrop.lib.helpers import content_type_for_response, url_for, redirect
from mediadrop.model import Media, Podcast, fetch_row
from mediadrop.plugin import events
from mediadrop.validation import LimitFeedItemsValidator
import logging
log = logging.getLogger(__name__)
class PodcastsController(BaseController):
"""
Podcast Series Controller
This handles episode collections, individual episodes are handled as
regular media by :mod:`mediadrop.controllers.media`.
"""
@expose('podcasts/index.html')
@observable(events.PodcastsController.index)
def index(self, **kwargs):
"""List podcasts and podcast media.
:rtype: dict
:returns:
podcasts
The :class:`~mediadrop.model.podcasts.Podcast` instance
"""
podcasts = Podcast.query\
.options(orm.undefer('media_count_published'))\
.all()
if len(podcasts) == 1:
redirect(action='view', slug=podcasts[0].slug)
podcast_episodes = {}
for podcast in podcasts:
episode_query = podcast.media.published().order_by(Media.publish_on.desc())
podcast_episodes[podcast] = viewable_media(episode_query)[:4]
return dict(
podcasts = podcasts,
podcast_episodes = podcast_episodes,
)
@expose('podcasts/view.html')
@paginate('episodes', items_per_page=10)
@observable(events.PodcastsController.view)
def view(self, slug, page=1, show='latest', **kwargs):
"""View a podcast and the media that belongs to it.
:param slug: A :attr:`~mediadrop.model.podcasts.Podcast.slug`
:param page: Page number, defaults to 1.
:type page: int
:rtype: dict
:returns:
podcast
A :class:`~mediadrop.model.podcasts.Podcast` instance.
episodes
A list of :class:`~mediadrop.model.media.Media` instances
that belong to the ``podcast``.
podcasts
A list of all the other podcasts
"""
podcast = fetch_row(Podcast, slug=slug)
episodes = podcast.media.published()
episodes, show = helpers.filter_library_controls(episodes, show)
episodes = viewable_media(episodes)
if request.settings['rss_display'] == 'True':
response.feed_links.append(
(url_for(action='feed'), podcast.title)
)
return dict(
podcast = podcast,
episodes = episodes,
result_count = episodes.count(),
show = show,
)
@validate(validators={'limit': LimitFeedItemsValidator()})
@beaker_cache(expire=60 * 20)
@expose('podcasts/feed.xml')
@observable(events.PodcastsController.feed)
def feed(self, slug, limit=None, **kwargs):
"""Serve the feed as RSS 2.0.
If :attr:`~mediadrop.model.podcasts.Podcast.feedburner_url` is
specified for this podcast, we redirect there if the useragent
does not contain 'feedburner', as described here:
http://www.google.com/support/feedburner/bin/answer.py?hl=en&answer=78464
:param feedburner_bypass: If true, the redirect to feedburner is disabled.
:rtype: Dict
:returns:
podcast
A :class:`~mediadrop.model.podcasts.Podcast` instance.
episodes
A list of :class:`~mediadrop.model.media.Media` instances
that belong to the ``podcast``.
Renders: :data:`podcasts/feed.xml` XML
"""
podcast = fetch_row(Podcast, slug=slug)
if (podcast.feedburner_url
and not 'feedburner' in request.environ.get('HTTP_USER_AGENT', '').lower()
and not kwargs.get('feedburner_bypass', False)):
redirect(podcast.feedburner_url.encode('utf-8'))
response.content_type = content_type_for_response(
['application/rss+xml', 'application/xml', 'text/xml'])
episode_query = podcast.media.published().order_by(Media.publish_on.desc())
episodes = viewable_media(episode_query)
if limit is not None:
episodes = episodes.limit(limit)
return dict(
podcast = podcast,
episodes = episodes,
)