properly register auto-flattr celery task
[mygpo.git] / mygpo / api / backend.py
blob24ecf9b8587ff621bffba9dc27897293fdae74fb
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from collections import defaultdict
19 from functools import partial
21 from mygpo.core.models import Podcast, Episode
22 from mygpo.users.models import EpisodeUserState, Device, DeviceDoesNotExist, \
23 PodcastUserState
24 from mygpo.decorators import repeat_on_conflict
25 from mygpo.couch import bulk_save_retry
26 from mygpo.json import json
27 from mygpo.users.settings import STORE_UA
28 from mygpo.db.couchdb.podcast import podcast_for_url, random_podcasts
29 from mygpo.db.couchdb.podcast_state import podcast_state_for_user_podcast
32 def get_random_picks(languages=None):
33 """ Returns random podcasts for the given language """
35 languages = languages or ['']
37 # get one iterator for each language
38 rand_iters = [random_podcasts(lang) for lang in languages]
40 # cycle through them, removing those that don't yield any more results
41 while rand_iters:
42 rand_iter = rand_iters.pop(0)
44 try:
45 podcast = next(rand_iter)
46 rand_iters.append(rand_iter)
47 yield podcast
49 except StopIteration:
50 # don't re-add rand_iter
51 pass
55 @repeat_on_conflict(['user'])
56 def get_device(user, uid, user_agent, undelete=True):
57 """
58 Loads or creates the device indicated by user, uid.
60 If the device has been deleted and undelete=True, it is undeleted.
61 """
63 store_ua = user.get_wksetting(STORE_UA)
65 save = False
67 try:
68 device = user.get_device_by_uid(uid, only_active=False)
70 except DeviceDoesNotExist:
71 device = Device(uid=uid)
72 user.devices.append(device)
73 save = True
75 if device.deleted and undelete:
76 device.deleted = False
77 user.set_device(device)
78 save = True
80 if store_ua and user_agent and \
81 getattr(device, 'user_agent', None) != user_agent:
82 device.user_agent = user_agent
83 user.set_device(device)
84 save = True
86 if save:
87 user.save()
89 return device
92 class BulkSubscribe(object):
93 """ Performs bulk subscribe/unsubscribe operations """
95 def __init__(self, user, device, podcasts = {}, actions=None):
96 self.user = user
97 self.device = device
98 self.podcasts = podcasts
99 self.actions = actions or []
101 self.operations = {
102 'subscribe': partial(self._subscribe, device=device),
103 'unsubscribe': partial(self._unsubscribe, device=device),
107 def execute(self):
108 """ Executes all added actions in bulk """
109 obj_funs = map(self._get_obj_fun, self.actions)
110 bulk_save_retry(obj_funs)
112 # prepare for another run
113 self.actions = []
116 def add_action(self, url, op):
117 """ Adds a new (un)subscribe action
119 url is the podcast url to subscribe to / unsubscribe from
120 op is either "subscribe" or "unsubscribe" """
121 self.actions.append( (url, op) )
124 def _get_obj_fun(self, action):
125 url, op = action
127 podcast = self.podcasts.get(url,
128 podcast_for_url(url, create=True))
130 state = podcast_state_for_user_podcast(self.user, podcast)
132 fun = self.operations[op]
133 return (state, fun)
137 def _subscribe(self, state, device):
138 state.subscribe(device)
139 return state
141 def _unsubscribe(self, state, device):
142 state.unsubscribe(device)
143 return state