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 def get_device(user
, uid
, user_agent
, undelete
=True):
57 Loads or creates the device indicated by user, uid.
59 If the device has been deleted and undelete=True, it is undeleted.
62 store_ua
= user
.get_wksetting(STORE_UA
)
64 @repeat_on_conflict(['user'])
65 def _get(user
, uid
, undelete
):
70 device
= user
.get_device_by_uid(uid
, only_active
=False)
72 except DeviceDoesNotExist
:
73 device
= Device(uid
=uid
)
74 user
.devices
.append(device
)
77 if device
.deleted
and undelete
:
78 device
.deleted
= False
79 user
.set_device(device
)
82 if store_ua
and user_agent
and \
83 getattr(device
, 'user_agent', None) != user_agent
:
84 device
.user_agent
= user_agent
85 user
.set_device(device
)
93 return _get(user
=user
, uid
=uid
, undelete
=undelete
)
96 class BulkSubscribe(object):
97 """ Performs bulk subscribe/unsubscribe operations """
99 def __init__(self
, user
, device
, podcasts
= {}, actions
=None):
102 self
.podcasts
= podcasts
103 self
.actions
= actions
or []
106 'subscribe': partial(self
._subscribe
, device
=device
),
107 'unsubscribe': partial(self
._unsubscribe
, device
=device
),
112 """ Executes all added actions in bulk """
113 obj_funs
= map(self
._get
_obj
_fun
, self
.actions
)
114 bulk_save_retry(obj_funs
)
116 # prepare for another run
120 def add_action(self
, url
, op
):
121 """ Adds a new (un)subscribe action
123 url is the podcast url to subscribe to / unsubscribe from
124 op is either "subscribe" or "unsubscribe" """
125 self
.actions
.append( (url
, op
) )
128 def _get_obj_fun(self
, action
):
131 podcast
= self
.podcasts
.get(url
,
132 podcast_for_url(url
, create
=True))
134 state
= podcast_state_for_user_podcast(self
.user
, podcast
)
136 fun
= self
.operations
[op
]
141 def _subscribe(self
, state
, device
):
142 state
.subscribe(device
)
145 def _unsubscribe(self
, state
, device
):
146 state
.unsubscribe(device
)