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
, \
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
42 rand_iter
= rand_iters
.pop(0)
45 podcast
= next(rand_iter
)
46 rand_iters
.append(rand_iter
)
50 # don't re-add rand_iter
55 @repeat_on_conflict(['user'])
56 def get_device(user
, uid
, user_agent
, undelete
=True):
58 Loads or creates the device indicated by user, uid.
60 If the device has been deleted and undelete=True, it is undeleted.
63 store_ua
= user
.get_wksetting(STORE_UA
)
68 device
= user
.get_device_by_uid(uid
, only_active
=False)
70 except DeviceDoesNotExist
:
71 device
= Device(uid
=uid
)
72 user
.devices
.append(device
)
75 if device
.deleted
and undelete
:
76 device
.deleted
= False
77 user
.set_device(device
)
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
)
92 class BulkSubscribe(object):
93 """ Performs bulk subscribe/unsubscribe operations """
95 def __init__(self
, user
, device
, podcasts
= {}, actions
=None):
98 self
.podcasts
= podcasts
99 self
.actions
= actions
or []
102 'subscribe': partial(self
._subscribe
, device
=device
),
103 'unsubscribe': partial(self
._unsubscribe
, device
=device
),
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
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
):
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
]
137 def _subscribe(self
, state
, device
):
138 state
.subscribe(device
)
141 def _unsubscribe(self
, state
, device
):
142 state
.unsubscribe(device
)