diff options
Diffstat (limited to 'pandora/client.py')
-rw-r--r-- | pandora/client.py | 215 |
1 files changed, 119 insertions, 96 deletions
diff --git a/pandora/client.py b/pandora/client.py index e0d3da9..a98056c 100644 --- a/pandora/client.py +++ b/pandora/client.py | |||
@@ -29,8 +29,14 @@ class BaseAPIClient: | |||
29 | 29 | ||
30 | ALL_QUALITIES = [LOW_AUDIO_QUALITY, MED_AUDIO_QUALITY, HIGH_AUDIO_QUALITY] | 30 | ALL_QUALITIES = [LOW_AUDIO_QUALITY, MED_AUDIO_QUALITY, HIGH_AUDIO_QUALITY] |
31 | 31 | ||
32 | def __init__(self, transport, partner_user, partner_password, device, | 32 | def __init__( |
33 | default_audio_quality=MED_AUDIO_QUALITY): | 33 | self, |
34 | transport, | ||
35 | partner_user, | ||
36 | partner_password, | ||
37 | device, | ||
38 | default_audio_quality=MED_AUDIO_QUALITY, | ||
39 | ): | ||
34 | self.transport = transport | 40 | self.transport = transport |
35 | self.partner_user = partner_user | 41 | self.partner_user = partner_user |
36 | self.partner_password = partner_password | 42 | self.partner_password = partner_password |
@@ -40,11 +46,13 @@ class BaseAPIClient: | |||
40 | self.password = None | 46 | self.password = None |
41 | 47 | ||
42 | def _partner_login(self): | 48 | def _partner_login(self): |
43 | partner = self.transport("auth.partnerLogin", | 49 | partner = self.transport( |
44 | username=self.partner_user, | 50 | "auth.partnerLogin", |
45 | password=self.partner_password, | 51 | username=self.partner_user, |
46 | deviceModel=self.device, | 52 | password=self.partner_password, |
47 | version=self.transport.API_VERSION) | 53 | deviceModel=self.device, |
54 | version=self.transport.API_VERSION, | ||
55 | ) | ||
48 | 56 | ||
49 | self.transport.set_partner(partner) | 57 | self.transport.set_partner(partner) |
50 | 58 | ||
@@ -59,16 +67,18 @@ class BaseAPIClient: | |||
59 | self._partner_login() | 67 | self._partner_login() |
60 | 68 | ||
61 | try: | 69 | try: |
62 | user = self.transport("auth.userLogin", | 70 | user = self.transport( |
63 | loginType="user", | 71 | "auth.userLogin", |
64 | username=self.username, | 72 | loginType="user", |
65 | password=self.password, | 73 | username=self.username, |
66 | includePandoraOneInfo=True, | 74 | password=self.password, |
67 | includeSubscriptionExpiration=True, | 75 | includePandoraOneInfo=True, |
68 | returnCapped=True, | 76 | includeSubscriptionExpiration=True, |
69 | includeAdAttributes=True, | 77 | returnCapped=True, |
70 | includeAdvertiserAttributes=True, | 78 | includeAdAttributes=True, |
71 | xplatformAdCapable=True) | 79 | includeAdvertiserAttributes=True, |
80 | xplatformAdCapable=True, | ||
81 | ) | ||
72 | except errors.InvalidPartnerLogin: | 82 | except errors.InvalidPartnerLogin: |
73 | raise errors.InvalidUserLogin() | 83 | raise errors.InvalidUserLogin() |
74 | 84 | ||
@@ -80,7 +90,7 @@ class BaseAPIClient: | |||
80 | def get_qualities(cls, start_at, return_all_if_invalid=True): | 90 | def get_qualities(cls, start_at, return_all_if_invalid=True): |
81 | try: | 91 | try: |
82 | idx = cls.ALL_QUALITIES.index(start_at) | 92 | idx = cls.ALL_QUALITIES.index(start_at) |
83 | return cls.ALL_QUALITIES[:idx + 1] | 93 | return cls.ALL_QUALITIES[: idx + 1] |
84 | except ValueError: | 94 | except ValueError: |
85 | if return_all_if_invalid: | 95 | if return_all_if_invalid: |
86 | return cls.ALL_QUALITIES[:] | 96 | return cls.ALL_QUALITIES[:] |
@@ -105,9 +115,9 @@ class APIClient(BaseAPIClient): | |||
105 | def get_station_list(self): | 115 | def get_station_list(self): |
106 | from .models.station import StationList | 116 | from .models.station import StationList |
107 | 117 | ||
108 | return StationList.from_json(self, | 118 | return StationList.from_json( |
109 | self("user.getStationList", | 119 | self, self("user.getStationList", includeStationArtUrl=True) |
110 | includeStationArtUrl=True)) | 120 | ) |
111 | 121 | ||
112 | def get_station_list_checksum(self): | 122 | def get_station_list_checksum(self): |
113 | return self("user.getStationListChecksum")["checksum"] | 123 | return self("user.getStationListChecksum")["checksum"] |
@@ -119,19 +129,21 @@ class APIClient(BaseAPIClient): | |||
119 | additional_urls = [] | 129 | additional_urls = [] |
120 | 130 | ||
121 | if isinstance(additional_urls, str): | 131 | if isinstance(additional_urls, str): |
122 | raise TypeError('Additional urls should be a list') | 132 | raise TypeError("Additional urls should be a list") |
123 | 133 | ||
124 | urls = [getattr(url, "value", url) for url in additional_urls] | 134 | urls = [getattr(url, "value", url) for url in additional_urls] |
125 | 135 | ||
126 | resp = self("station.getPlaylist", | 136 | resp = self( |
127 | stationToken=station_token, | 137 | "station.getPlaylist", |
128 | includeTrackLength=True, | 138 | stationToken=station_token, |
129 | xplatformAdCapable=True, | 139 | includeTrackLength=True, |
130 | audioAdPodCapable=True, | 140 | xplatformAdCapable=True, |
131 | additionalAudioUrl=','.join(urls)) | 141 | audioAdPodCapable=True, |
142 | additionalAudioUrl=",".join(urls), | ||
143 | ) | ||
132 | 144 | ||
133 | for item in resp['items']: | 145 | for item in resp["items"]: |
134 | item['_paramAdditionalUrls'] = additional_urls | 146 | item["_paramAdditionalUrls"] = additional_urls |
135 | 147 | ||
136 | playlist = Playlist.from_json(self, resp) | 148 | playlist = Playlist.from_json(self, resp) |
137 | 149 | ||
@@ -145,58 +157,69 @@ class APIClient(BaseAPIClient): | |||
145 | def get_bookmarks(self): | 157 | def get_bookmarks(self): |
146 | from .models.bookmark import BookmarkList | 158 | from .models.bookmark import BookmarkList |
147 | 159 | ||
148 | return BookmarkList.from_json(self, | 160 | return BookmarkList.from_json(self, self("user.getBookmarks")) |
149 | self("user.getBookmarks")) | ||
150 | 161 | ||
151 | def get_station(self, station_token): | 162 | def get_station(self, station_token): |
152 | from .models.station import Station | 163 | from .models.station import Station |
153 | 164 | ||
154 | return Station.from_json(self, | 165 | return Station.from_json( |
155 | self("station.getStation", | 166 | self, |
156 | stationToken=station_token, | 167 | self( |
157 | includeExtendedAttributes=True)) | 168 | "station.getStation", |
169 | stationToken=station_token, | ||
170 | includeExtendedAttributes=True, | ||
171 | ), | ||
172 | ) | ||
158 | 173 | ||
159 | def add_artist_bookmark(self, track_token): | 174 | def add_artist_bookmark(self, track_token): |
160 | return self("bookmark.addArtistBookmark", | 175 | return self("bookmark.addArtistBookmark", trackToken=track_token) |
161 | trackToken=track_token) | ||
162 | 176 | ||
163 | def add_song_bookmark(self, track_token): | 177 | def add_song_bookmark(self, track_token): |
164 | return self("bookmark.addSongBookmark", | 178 | return self("bookmark.addSongBookmark", trackToken=track_token) |
165 | trackToken=track_token) | ||
166 | 179 | ||
167 | def delete_song_bookmark(self, bookmark_token): | 180 | def delete_song_bookmark(self, bookmark_token): |
168 | return self("bookmark.deleteSongBookmark", | 181 | return self( |
169 | bookmarkToken=bookmark_token) | 182 | "bookmark.deleteSongBookmark", bookmarkToken=bookmark_token |
183 | ) | ||
170 | 184 | ||
171 | def delete_artist_bookmark(self, bookmark_token): | 185 | def delete_artist_bookmark(self, bookmark_token): |
172 | return self("bookmark.deleteArtistBookmark", | 186 | return self( |
173 | bookmarkToken=bookmark_token) | 187 | "bookmark.deleteArtistBookmark", bookmarkToken=bookmark_token |
188 | ) | ||
174 | 189 | ||
175 | def search(self, search_text, | 190 | def search( |
176 | include_near_matches=False, | 191 | self, |
177 | include_genre_stations=False): | 192 | search_text, |
193 | include_near_matches=False, | ||
194 | include_genre_stations=False, | ||
195 | ): | ||
178 | from .models.search import SearchResult | 196 | from .models.search import SearchResult |
179 | 197 | ||
180 | return SearchResult.from_json( | 198 | return SearchResult.from_json( |
181 | self, | 199 | self, |
182 | self("music.search", | 200 | self( |
183 | searchText=search_text, | 201 | "music.search", |
184 | includeNearMatches=include_near_matches, | 202 | searchText=search_text, |
185 | includeGenreStations=include_genre_stations) | 203 | includeNearMatches=include_near_matches, |
204 | includeGenreStations=include_genre_stations, | ||
205 | ), | ||
186 | ) | 206 | ) |
187 | 207 | ||
188 | def add_feedback(self, track_token, positive): | 208 | def add_feedback(self, track_token, positive): |
189 | return self("station.addFeedback", | 209 | return self( |
190 | trackToken=track_token, | 210 | "station.addFeedback", trackToken=track_token, isPositive=positive |
191 | isPositive=positive) | 211 | ) |
192 | 212 | ||
193 | def add_music(self, music_token, station_token): | 213 | def add_music(self, music_token, station_token): |
194 | return self("station.addMusic", | 214 | return self( |
195 | musicToken=music_token, | 215 | "station.addMusic", |
196 | stationToken=station_token) | 216 | musicToken=music_token, |
217 | stationToken=station_token, | ||
218 | ) | ||
197 | 219 | ||
198 | def create_station(self, search_token=None, artist_token=None, | 220 | def create_station( |
199 | track_token=None): | 221 | self, search_token=None, artist_token=None, track_token=None |
222 | ): | ||
200 | from .models.station import Station | 223 | from .models.station import Station |
201 | 224 | ||
202 | kwargs = {} | 225 | kwargs = {} |
@@ -210,26 +233,23 @@ class APIClient(BaseAPIClient): | |||
210 | else: | 233 | else: |
211 | raise KeyError("Must pass a type of token") | 234 | raise KeyError("Must pass a type of token") |
212 | 235 | ||
213 | return Station.from_json(self, | 236 | return Station.from_json(self, self("station.createStation", **kwargs)) |
214 | self("station.createStation", **kwargs)) | ||
215 | 237 | ||
216 | def delete_feedback(self, feedback_id): | 238 | def delete_feedback(self, feedback_id): |
217 | return self("station.deleteFeedback", | 239 | return self("station.deleteFeedback", feedbackId=feedback_id) |
218 | feedbackId=feedback_id) | ||
219 | 240 | ||
220 | def delete_music(self, seed_id): | 241 | def delete_music(self, seed_id): |
221 | return self("station.deleteMusic", | 242 | return self("station.deleteMusic", seedId=seed_id) |
222 | seedId=seed_id) | ||
223 | 243 | ||
224 | def delete_station(self, station_token): | 244 | def delete_station(self, station_token): |
225 | return self("station.deleteStation", | 245 | return self("station.deleteStation", stationToken=station_token) |
226 | stationToken=station_token) | ||
227 | 246 | ||
228 | def get_genre_stations(self): | 247 | def get_genre_stations(self): |
229 | from .models.station import GenreStationList | 248 | from .models.station import GenreStationList |
230 | 249 | ||
231 | genre_stations = GenreStationList.from_json( | 250 | genre_stations = GenreStationList.from_json( |
232 | self, self("station.getGenreStations")) | 251 | self, self("station.getGenreStations") |
252 | ) | ||
233 | genre_stations.checksum = self.get_genre_stations_checksum() | 253 | genre_stations.checksum = self.get_genre_stations_checksum() |
234 | 254 | ||
235 | return genre_stations | 255 | return genre_stations |
@@ -238,44 +258,45 @@ class APIClient(BaseAPIClient): | |||
238 | return self("station.getGenreStationsChecksum")["checksum"] | 258 | return self("station.getGenreStationsChecksum")["checksum"] |
239 | 259 | ||
240 | def rename_station(self, station_token, name): | 260 | def rename_station(self, station_token, name): |
241 | return self("station.renameStation", | 261 | return self( |
242 | stationToken=station_token, | 262 | "station.renameStation", |
243 | stationName=name) | 263 | stationToken=station_token, |
264 | stationName=name, | ||
265 | ) | ||
244 | 266 | ||
245 | def explain_track(self, track_token): | 267 | def explain_track(self, track_token): |
246 | return self("track.explainTrack", | 268 | return self("track.explainTrack", trackToken=track_token) |
247 | trackToken=track_token) | ||
248 | 269 | ||
249 | def set_quick_mix(self, *args): | 270 | def set_quick_mix(self, *args): |
250 | return self("user.setQuickMix", | 271 | return self("user.setQuickMix", quickMixStationIds=args) |
251 | quickMixStationIds=args) | ||
252 | 272 | ||
253 | def sleep_song(self, track_token): | 273 | def sleep_song(self, track_token): |
254 | return self("user.sleepSong", | 274 | return self("user.sleepSong", trackToken=track_token) |
255 | trackToken=track_token) | ||
256 | 275 | ||
257 | def share_station(self, station_id, station_token, *emails): | 276 | def share_station(self, station_id, station_token, *emails): |
258 | return self("station.shareStation", | 277 | return self( |
259 | stationId=station_id, | 278 | "station.shareStation", |
260 | stationToken=station_token, | 279 | stationId=station_id, |
261 | emails=emails) | 280 | stationToken=station_token, |
281 | emails=emails, | ||
282 | ) | ||
262 | 283 | ||
263 | def transform_shared_station(self, station_token): | 284 | def transform_shared_station(self, station_token): |
264 | return self("station.transformSharedStation", | 285 | return self( |
265 | stationToken=station_token) | 286 | "station.transformSharedStation", stationToken=station_token |
287 | ) | ||
266 | 288 | ||
267 | def share_music(self, music_token, *emails): | 289 | def share_music(self, music_token, *emails): |
268 | return self("music.shareMusic", | 290 | return self( |
269 | musicToken=music_token, | 291 | "music.shareMusic", musicToken=music_token, email=emails[0] |
270 | email=emails[0]) | 292 | ) |
271 | 293 | ||
272 | def get_ad_item(self, station_id, ad_token): | 294 | def get_ad_item(self, station_id, ad_token): |
273 | from .models.ad import AdItem | 295 | from .models.ad import AdItem |
274 | 296 | ||
275 | if not station_id: | 297 | if not station_id: |
276 | raise errors.ParameterMissing("The 'station_id' param must be " | 298 | msg = "The 'station_id' param must be defined, got: '{}'" |
277 | "defined, got: '{}'" | 299 | raise errors.ParameterMissing(msg.format(station_id)) |
278 | .format(station_id)) | ||
279 | 300 | ||
280 | ad_item = AdItem.from_json(self, self.get_ad_metadata(ad_token)) | 301 | ad_item = AdItem.from_json(self, self.get_ad_metadata(ad_token)) |
281 | ad_item.station_id = station_id | 302 | ad_item.station_id = station_id |
@@ -283,12 +304,14 @@ class APIClient(BaseAPIClient): | |||
283 | return ad_item | 304 | return ad_item |
284 | 305 | ||
285 | def get_ad_metadata(self, ad_token): | 306 | def get_ad_metadata(self, ad_token): |
286 | return self("ad.getAdMetadata", | 307 | return self( |
287 | adToken=ad_token, | 308 | "ad.getAdMetadata", |
288 | returnAdTrackingTokens=True, | 309 | adToken=ad_token, |
289 | supportAudioAds=True) | 310 | returnAdTrackingTokens=True, |
311 | supportAudioAds=True, | ||
312 | ) | ||
290 | 313 | ||
291 | def register_ad(self, station_id, tokens): | 314 | def register_ad(self, station_id, tokens): |
292 | return self("ad.registerAd", | 315 | return self( |
293 | stationId=station_id, | 316 | "ad.registerAd", stationId=station_id, adTrackingTokens=tokens |
294 | adTrackingTokens=tokens) | 317 | ) |