[Migration] fix typo
[mygpo.git] / mygpo / db / couchdb / podcast_state.py
blob0bd2e875bd0e3abd463f9088ad67147cf211fc61
1 from mygpo.users.models import PodcastUserState, SubscriptionException
2 from mygpo.users.settings import PUBLIC_SUB_PODCAST, PUBLIC_SUB_USER
3 from mygpo.db.couchdb import get_userdata_database, get_single_result
4 from mygpo.cache import cache_result
5 from mygpo.db import QueryParameterMissing
6 from mygpo.decorators import repeat_on_conflict
9 def all_podcast_states(podcast):
11 if not podcast:
12 raise QueryParameterMissing('podcast')
14 udb = get_userdata_database()
16 r = udb.view('podcast_states/by_podcast',
17 startkey = [podcast.get_id(), None],
18 endkey = [podcast.get_id(), {}],
19 include_docs = True,
20 schema = PodcastUserState,
23 states = list(r)
25 for state in states:
26 state.set_db(udb)
28 return states
31 @cache_result(timeout=60*60)
32 def subscribed_users(podcast):
34 if not podcast:
35 raise QueryParameterMissing('podcast')
37 udb = get_userdata_database()
39 res = udb.view('subscriptions/by_podcast',
40 startkey = [podcast.get_id(), None, None],
41 endkey = [podcast.get_id(), {}, {}],
42 group = True,
43 group_level = 2,
44 stale = 'update_after',
47 users = (r['key'][1] for r in res)
48 return users
51 def subscribed_podcast_ids_by_user_id(user_id):
53 if not user_id:
54 raise QueryParameterMissing('user_id')
56 udb = get_userdata_database()
58 subscribed = udb.view('subscriptions/by_user',
59 startkey = [user_id, True, None, None],
60 endkey = [user_id, True, {}, {}],
61 group = True,
62 group_level = 3,
63 stale = 'update_after',
65 return set(r['key'][2] for r in subscribed)
68 @cache_result(timeout=60*60)
69 def podcast_subscriber_count(podcast):
71 if not podcast:
72 raise QueryParameterMissing('podcast')
74 udb = get_userdata_database()
75 subscriber_sum = 0
77 for podcast_id in podcast.get_ids():
78 x = get_single_result(udb, 'subscribers/by_podcast',
79 startkey = [podcast_id, None],
80 endkey = [podcast_id, {}],
81 reduce = True,
82 group = True,
83 group_level = 1,
86 subscriber_sum += x['value'] if x else 0
88 return subscriber_sum
91 def podcast_state_for_user_podcast(user, podcast):
93 if not user:
94 raise QueryParameterMissing('user')
96 if not podcast:
97 raise QueryParameterMissing('podcast')
99 udb = get_userdata_database()
101 p = get_single_result(udb, 'podcast_states/by_podcast',
102 key = [podcast.get_id(), user._id],
103 limit = 1,
104 include_docs = True,
105 schema = PodcastUserState,
108 if not p:
109 p = PodcastUserState()
110 p.podcast = podcast.get_id()
111 p.user = user._id
112 p.ref_url = podcast.url
113 p.settings[PUBLIC_SUB_PODCAST.name]=user.get_wksetting(PUBLIC_SUB_USER)
115 p.set_device_state(user.devices)
117 return p
120 def podcast_states_for_user(user):
122 if not user:
123 raise QueryParameterMissing('user')
125 udb = get_userdata_database()
127 r = udb.view('podcast_states/by_user',
128 startkey = [user._id, None],
129 endkey = [user._id, 'ZZZZ'],
130 include_docs = True,
131 schema = PodcastUserState,
134 states = list(r)
135 for state in states:
136 state.set_db(udb)
138 return states
141 def podcast_states_for_device(device_id):
143 if not device_id:
144 raise QueryParameterMissing('device_id')
146 udb = get_userdata_database()
148 r = udb.view('podcast_states/by_device',
149 startkey = [device_id, None],
150 endkey = [device_id, {}],
151 include_docs = True,
152 schema = PodcastUserState,
155 states = list(r)
157 for state in states:
158 state.set_db(udb)
160 return states
163 @cache_result(timeout=60*60)
164 def podcast_state_count():
165 udb = get_userdata_database()
166 r = udb.view('podcast_states/by_user',
167 limit = 0,
168 stale = 'update_after',
170 return r.total_rows
173 def subscribed_podcast_ids_by_device(device):
175 if not device:
176 raise QueryParameterMissing('device')
178 udb = get_userdata_database()
179 r = udb.view('subscriptions/by_device',
180 startkey = [device.id, None],
181 endkey = [device.id, {}]
183 return [res['key'][1] for res in r]
186 def subscriptions_by_user(user, public=None):
188 Returns a list of (podcast-id, device-id) tuples for all
189 of the users subscriptions
192 if not user:
193 raise QueryParameterMissing('user')
195 udb = get_userdata_database()
197 r = udb.view('subscriptions/by_user',
198 startkey = [user._id, public, None, None],
199 endkey = [user._id+'ZZZ', None, None, None],
200 reduce = False,
201 schema = PodcastUserState,
203 return [res['key'][1:] for res in r]
206 @repeat_on_conflict(['state'])
207 def add_subscription_action(state, action):
208 udb = get_userdata_database()
209 state.add_actions([action])
210 udb.save_doc(state)
213 @repeat_on_conflict(['state'])
214 def delete_podcast_state(state):
215 udb = get_userdata_database()
216 udb.delete_doc(state)
219 @repeat_on_conflict(['state'])
220 def add_podcast_tags(state, tags):
221 udb = get_userdata_database()
222 state.add_tags(tags)
223 udb.save_doc(state)
225 @repeat_on_conflict(['state'])
226 def remove_podcast_tags(state, tag_str):
227 if tag_str not in state.tags:
228 return
229 udb = get_userdata_database()
230 state.tags.remove(tag_str)
231 udb.save_doc(state)
234 @repeat_on_conflict(['state'])
235 def set_podcast_privacy_settings(state, is_public):
236 udb = get_userdata_database()
237 state.settings[PUBLIC_SUB_PODCAST.name] = is_public
238 udb.save_doc(state)
241 @repeat_on_conflict(['state'])
242 def remove_device_from_podcast_state(state, dev):
243 udb = get_userdata_database()
244 state.remove_device(dev)
245 udb.save_doc(state)
247 @repeat_on_conflict(['state'])
248 def subscribe_on_device(state, device):
249 state.subscribe(device)
250 udb = get_userdata_database()
251 udb.save_doc(state)
253 @repeat_on_conflict(['state'])
254 def unsubscribe_on_device(state, device):
255 state.unsubscribe(device)
256 udb = get_userdata_database()
257 udb.save_doc(state)
260 @repeat_on_conflict(['state'])
261 def update_podcast_state_podcast(state, new_id, new_url):
262 state.ref_url = new_url
263 state.podcast = new_id
264 udb = get_userdata_database()
265 udb.save_doc(state)
268 @repeat_on_conflict(['state'])
269 def merge_podcast_states(state, state2):
270 # overwrite settings in state2 with state's settings
271 settings = state2.settings
272 settings.update(state.settings)
273 state.settings = settings
276 disabled_devices = state.disabled_devices + state2.disabled_devices
277 disabled_devices = filter(None, set(disabled_devices))
278 state.disabled_devices = disabled_devices
280 merged_ids = state.merged_ids + [state2._id] + state2.merged_ids
281 merged_ids = set(filter(None, merged_ids))
282 merged_ids = list(merged_ids - set([state._id]))
283 state.merged_ids = merged_ids
285 tags = state.tags + state2.tags
286 tags = filter(None, set(tags))
287 state.tags = tags
289 udb = get_userdata_database()
290 udb.save_doc(state)
293 def get_subscribed_podcast_states_by_device(device):
294 udb = get_userdata_database()
295 r = udb.view('subscriptions/by_device',
296 startkey = [device.id, None],
297 endkey = [device.id, {}],
298 include_docs = True,
299 schema = PodcastUserState,
302 states = list(r)
304 for state in states:
305 state.set_db(udb)
307 return states
310 def get_subscribed_podcast_states_by_user(user, public=None):
312 Returns the Ids of all subscribed podcasts
315 udb = get_userdata_database()
316 r = udb.view('subscriptions/by_user',
317 startkey = [user._id, public, None, None],
318 endkey = [user._id, {}, {}, {}],
319 reduce = False,
320 include_docs = True,
321 schema = PodcastUserState,
324 states = list(r)
326 for state in states:
327 state.set_db(udb)
329 return states
332 @repeat_on_conflict()
333 def subscribe(podcast, user, device):
334 """ subscribes user to the current podcast on one or more devices """
335 from mygpo.core.signals import subscription_changed
336 state = podcast_state_for_user_podcast(user, podcast)
338 # accept devices, and also lists and tuples of devices
339 devices = device if isinstance(device, (list, tuple)) else [device]
341 for device in devices:
343 try:
344 subscribe_on_device(state, device)
345 subscription_changed.send(sender=podcast, user=user,
346 device=device, subscribed=True)
347 except Unauthorized as ex:
348 raise SubscriptionException(ex)
351 @repeat_on_conflict()
352 def unsubscribe(podcast, user, device):
353 """ unsubscribes user from the current podcast on one or more devices """
354 from mygpo.core.signals import subscription_changed
355 state = podcast_state_for_user_podcast(user, podcast)
357 # accept devices, and also lists and tuples of devices
358 devices = device if isinstance(device, (list, tuple)) else [device]
360 for device in devices:
362 try:
363 unsubscribe_on_device(state, device)
364 subscription_changed.send(sender=podcast, user=user, device=device,
365 subscribed=False)
366 except Unauthorized as ex:
367 raise SubscriptionException(ex)