1 from hashlib
import sha1
2 from datetime
import datetime
4 from django
.core
.cache
import cache
6 from mygpo
.core
.models
import Podcast
, Episode
, MergedIdException
7 from mygpo
.cache
import cache_result
8 from mygpo
.db
import QueryParameterMissing
9 from mygpo
.db
.couchdb
.utils
import is_couchdb_id
10 from mygpo
.db
.couchdb
import get_main_database
11 from mygpo
.db
.couchdb
.podcast
import podcast_for_url
, podcast_for_slug_id
14 @cache_result(timeout
=60*60)
15 def episode_by_id(episode_id
, current_id
=False):
18 raise QueryParameterMissing('episode_id')
20 r
= Episode
.view('episodes/by_id',
29 if current_id
and obj
._id
!= episode_id
:
30 raise MergedIdException(obj
, obj
._id
)
35 @cache_result(timeout
=60*60)
36 def episodes_by_id(episode_ids
):
38 if episode_ids
is None:
39 raise QueryParameterMissing('episode_ids')
44 r
= Episode
.view('episodes/by_id',
51 @cache_result(timeout
=60*60)
52 def episode_for_oldid(oldid
):
55 raise QueryParameterMissing('oldid')
58 r
= Episode
.view('episodes/by_oldid',
63 return r
.one() if r
else None
66 @cache_result(timeout
=60*60)
67 def episode_for_slug(podcast_id
, episode_slug
):
70 raise QueryParameterMissing('podcast_id')
73 raise QueryParameterMissing('episode_slug')
76 r
= Episode
.view('episodes/by_slug',
77 key
= [podcast_id
, episode_slug
],
80 return r
.first() if r
else None
83 def episode_for_podcast_url(podcast_url
, episode_url
, create
=False):
86 raise QueryParameterMissing('podcast_url')
89 raise QueryParameterMissing('episode_url')
92 podcast
= podcast_for_url(podcast_url
, create
=create
)
94 if not podcast
: # podcast does not exist and should not be created
97 return episode_for_podcast_id_url(podcast
.get_id(), episode_url
, create
)
100 def episode_for_podcast_id_url(podcast_id
, episode_url
, create
=False):
103 raise QueryParameterMissing('podcast_id')
106 raise QueryParameterMissing('episode_url')
109 key
= u
'episode-podcastid-%s-url-%s' % (
110 sha1(podcast_id
.encode('utf-8')).hexdigest(),
111 sha1(episode_url
.encode('utf-8')).hexdigest())
113 episode
= cache
.get(key
)
117 r
= Episode
.view('episodes/by_podcast_url',
118 key
= [podcast_id
, episode_url
],
125 cache
.set(key
, episode
)
130 episode
.podcast
= podcast_id
131 episode
.urls
= [episode_url
]
133 cache
.set(key
, episode
)
139 @cache_result(timeout
=60*60)
140 def episode_for_slug_id(p_slug_id
, e_slug_id
):
141 """ Returns the Episode for Podcast Slug/Id and Episode Slug/Id """
144 raise QueryParameterMissing('p_slug_id')
147 raise QueryParameterMissing('e_slug_id')
150 # The Episode-Id is unique, so take that
151 if is_couchdb_id(e_slug_id
):
152 return episode_by_id(e_slug_id
)
154 # If we search using a slug, we need the Podcast's Id
155 if is_couchdb_id(p_slug_id
):
158 podcast
= podcast_for_slug_id(p_slug_id
)
163 p_id
= podcast
.get_id()
165 return episode_for_slug(p_id
, e_slug_id
)
168 @cache_result(timeout
=60*60)
170 r
= Episode
.view('episodes/by_podcast',
172 stale
= 'update_after',
174 return r
.one()['value'] if r
else 0
177 def episodes_to_dict(ids
, use_cache
=False):
180 raise QueryParameterMissing('ids')
191 res
= cache
.get_many(ids
)
192 cache_objs
.extend(res
.values())
193 ids
= [x
for x
in ids
if x
not in res
.keys()]
195 db_objs
= list(episodes_by_id(ids
))
197 for obj
in (cache_objs
+ db_objs
):
199 # get_multi returns dict {'key': _id, 'error': 'not found'}
200 # for non-existing objects
201 if isinstance(obj
, dict) and 'error' in obj
:
206 for i
in obj
.get_ids():
210 cache
.set_many(dict( (obj
._id
, obj
) for obj
in db_objs
))
215 def episode_slugs_per_podcast(podcast_id
, base_slug
):
218 raise QueryParameterMissing('podcast_id')
221 res
= Episode
.view('episodes/by_slug',
222 startkey
= [podcast_id
, base_slug
],
223 endkey
= [podcast_id
, base_slug
+ 'ZZZZZ'],
226 return [r
['key'][1] for r
in res
]
229 def episodes_for_podcast_uncached(podcast
, since
=None, until
={}, **kwargs
):
232 raise QueryParameterMissing('podcast')
235 if kwargs
.get('descending', False):
236 since
, until
= until
, since
238 if isinstance(since
, datetime
):
239 since
= since
.isoformat()
241 if isinstance(until
, datetime
):
242 until
= until
.isoformat()
244 res
= Episode
.view('episodes/by_podcast',
245 startkey
= [podcast
.get_id(), since
],
246 endkey
= [podcast
.get_id(), until
],
255 episodes_for_podcast
= cache_result(timeout
=60*60)(episodes_for_podcast_uncached
)
258 @cache_result(timeout
=60*60)
259 def episode_count_for_podcast(podcast
, since
=None, until
={}, **kwargs
):
262 raise QueryParameterMissing('podcast')
265 if kwargs
.get('descending', False):
266 since
, until
= until
, since
268 if isinstance(since
, datetime
):
269 since
= since
.isoformat()
271 if isinstance(until
, datetime
):
272 until
= until
.isoformat()
274 res
= Episode
.view('episodes/by_podcast',
275 startkey
= [podcast
.get_id(), since
],
276 endkey
= [podcast
.get_id(), until
],
282 return res
.one()['value']
285 def favorite_episodes_for_user(user
):
288 raise QueryParameterMissing('user')
290 favorites
= Episode
.view('favorites/episodes_by_user',
294 return list(favorites
)
297 def chapters_for_episode(episode_id
):
300 raise QueryParameterMissing('episode_id')
302 db
= get_main_database()
303 r
= db
.view('chapters/by_episode',
304 startkey
= [episode_id
, None],
305 endkey
= [episode_id
, {}],
308 return map(_wrap_chapter
, r
)
311 def _wrap_chapter(res
):
312 from mygpo
.users
.models
import Chapter
314 chapter
= Chapter
.wrap(res
['value'])
315 return (user
, chapter
)