3 from mygpo
.users
.models
import EpisodeUserState
4 from mygpo
.db
.couchdb
.podcast
import podcast_by_id
5 from mygpo
.db
.couchdb
.episode
import episode_for_podcast_id_url
6 from mygpo
.couch
import get_main_database
7 from mygpo
.cache
import cache_result
11 def episode_state_for_user_episode(user
, episode
):
12 r
= EpisodeUserState
.view('episode_states/by_user_episode',
13 key
= [user
._id
, episode
._id
],
22 podcast
= podcast_by_id(episode
.podcast
)
24 state
= EpisodeUserState()
25 state
.episode
= episode
._id
26 state
.podcast
= episode
.podcast
28 state
.ref_url
= episode
.url
29 state
.podcast_ref_url
= podcast
.url
35 def all_episode_states(episode
):
36 r
= EpisodeUserState
.view('episode_states/by_podcast_episode',
37 startkey
= [episode
.podcast
, episode
._id
, None],
38 endkey
= [episode
.podcast
, episode
._id
, {}],
45 def all_podcast_episode_states(podcast
):
46 r
= EpisodeUserState
.view('episode_states/by_podcast_episode',
47 startkey
= [podcast
.get_id(), None, None],
48 endkey
= [podcast
.get_id(), {}, {}],
55 @cache_result(timeout
=60*60)
56 def podcast_listener_count(episode
):
57 """ returns the number of users that have listened to this podcast """
59 r
= EpisodeUserState
.view('listeners/by_podcast',
60 startkey
= [episode
.get_id(), None],
61 endkey
= [episode
.get_id(), {}],
66 return r
.first()['value'] if r
else 0
69 def podcast_listener_count_timespan(podcast
, start
=None, end
={}):
70 """ returns (date, listener-count) tuples for all days w/ listeners """
72 if isinstance(start
, datetime
):
73 start
= start
.isoformat()
75 if isinstance(end
, datetime
):
78 r
= EpisodeUserState
.view('listeners/by_podcast',
79 startkey
= [podcast
.get_id(), start
],
80 endkey
= [podcast
.get_id(), end
],
86 return map(_wrap_listener_count
, r
)
89 @cache_result(timeout
=60*60)
90 def episode_listener_counts(episode
):
91 """ (Episode-Id, listener-count) tuples for episodes w/ listeners """
93 r
= EpisodeUserState
.view('listeners/by_podcast_episode',
94 startkey
= [episode
.get_id(), None, None],
95 endkey
= [episode
.get_id(), {}, {}],
101 return map(_wrap_listeners
)
105 def get_podcasts_episode_states(podcast
, user_id
):
106 """ Returns the latest episode actions for the podcast's episodes """
108 db
= get_main_database()
109 res
= db
.view('episode_states/by_user_podcast',
110 startkey
= [user_id
, podcast
.get_id(), None],
111 endkey
= [user_id
, podcast
.get_id(), {}],
114 return map(lambda r
: r
['value'], res
)
118 def episode_listener_count(episode
, start
=None, end
={}):
119 """ returns the number of users that have listened to this episode """
121 r
= EpisodeUserState
.view('listeners/by_episode',
122 startkey
= [episode
._id
, start
],
123 endkey
= [episode
._id
, end
],
128 return r
.first()['value'] if r
else 0
132 @cache_result(timeout
=60*60)
133 def episode_listener_count_timespan(episode
, start
=None, end
={}):
134 """ returns (date, listener-count) tuples for all days w/ listeners """
136 if isinstance(start
, datetime
):
137 start
= start
.isoformat()
139 if isinstance(end
, datetime
):
140 end
= end
.isoformat()
142 r
= EpisodeUserState
.view('listeners/by_episode',
143 startkey
= [episode
._id
, start
],
144 endkey
= [episode
._id
, end
],
150 return map(_wrap_listener_count
, r
)
154 def episode_state_for_ref_urls(user
, podcast_url
, episode_url
):
156 cache_key
= 'episode-state-%s-%s-%s' % (user
._id
,
157 hashlib
.md5(podcast_url
).hexdigest(),
158 hashlib
.md5(episode_url
).hexdigest())
160 state
= cache
.get(cache_key
)
164 res
= EpisodeUserState
.view('episode_states/by_ref_urls',
165 key
= [user
._id
, podcast_url
, episode_url
],
172 state
.ref_url
= episode_url
173 state
.podcast_ref_url
= podcast_url
174 cache
.set(cache_key
, state
, 60*60)
178 episode
= episode_for_podcast_id_url(podcast_url
, episode_url
,
180 return episode_state_for_user_episode(user
, episode
)
184 def get_episode_actions(user_id
, since
=None, until
={}, podcast_id
=None,
186 """ Returns Episode Actions for the given criteria"""
188 since_str
= since
.strftime('%Y-%m-%dT%H:%M:%S') if since
else None
189 until_str
= until
.strftime('%Y-%m-%dT%H:%M:%S') if until
else {}
191 if since_str
>= until_str
:
194 if not podcast_id
and not device_id
:
195 view
= 'episode_actions/by_user'
196 startkey
= [user_id
, since_str
]
197 endkey
= [user_id
, until_str
]
199 elif podcast_id
and not device_id
:
200 view
= 'episode_actions/by_podcast'
201 startkey
= [user_id
, podcast_id
, since_str
]
202 endkey
= [user_id
, podcast_id
, until_str
]
204 elif device_id
and not podcast_id
:
205 view
= 'episode_actions/by_device'
206 startkey
= [user_id
, device_id
, since_str
]
207 endkey
= [user_id
, device_id
, until_str
]
210 view
= 'episode_actions/by_podcast_device'
211 startkey
= [user_id
, podcast_id
, device_id
, since_str
]
212 endkey
= [user_id
, podcast_id
, device_id
, until_str
]
214 db
= get_main_database()
220 return map(lambda r
: r
['value'], res
)
224 @cache_result(timeout
=60*60)
225 def episode_states_count():
226 r
= cls
.view('episode_states/by_user_episode',
228 stale
= 'update_after',
233 def get_nth_episode_state(n
):
234 first
= EpisodeUserState
.view('episode_states/by_user_episode',
239 return first
.one() if first
else None
242 def get_duplicate_episode_states(user
, episode
):
243 states
= EpisodeUserState
.view('episode_states/by_user_episode',
244 key
= [user
, episode
],
250 def _wrap_listener_count(res
):
251 date
= parser
.parse(res
['key'][1]).date()
252 listeners
= res
['value']
253 return (date
, listeners
)
256 def _wrap_listeners(res
):
257 episode
= res
['key'][1]
258 listeners
= res
['value']
259 return (episode
, listeners
)
262 def get_heatmap(podcast_id
, episode_id
, user_id
):
263 db
= get_main_database()
265 group_level
= len(filter(None, [podcast_id
, episode_id
, user_id
]))
267 r
= db
.view('heatmap/by_episode',
268 startkey
= [podcast_id
, episode_id
, user_id
],
269 endkey
= [podcast_id
, episode_id
or {}, user_id
or {}],
272 group_level
= group_level
,
273 stale
= 'update_after',
280 res
= r
.first()['value']
281 return res
['heatmap'], res
['borders']