1 ///
2 /// Pandora messages.
3 /// @file       mediaunits/pandora/pandoramessages.cpp - pianod project
4 /// @author     Perette Barella
5 /// @date       2020-03-24
6 /// @copyright  Copyright 2020 Devious Fish. All rights reserved.
7 ///
8 
9 #pragma once
10 
11 #include <config.h>
12 
13 #include <string>
14 #include <memory>
15 
16 #include <parsnip.h>
17 
18 #include "musictypes.h"
19 #include "pandoratypes.h"
20 
21 namespace Pandora {
22     class Communication;
23     class Song;
24     class Artist;
25     class Station;
26 
27     extern const std::string Type_Track;
28     extern const std::string Type_Album;
29     extern const std::string Type_Artist;
30     extern const std::string Type_Station;
31     extern const std::string Type_StationFactory;
32 
33     /** Pandora request class.  This provides a framework for assembling
34         requests and decoding responses. */
35     class Request {
36         friend Communication;
37 
38     private:
39         /// Where there this request will be routed to within the REST API.
40         const std::string endpoint;
41 
42     protected:
43         Source *source;
44 
45         Request (Source *src, const char *ep);
46 
47         ThingieList extractAssortedThingsFromDictionary (const Parsnip::SerialData &message) const;
48 
49     public:
50         virtual bool debug() const;
51 
52         /** Convert request into a message as a Parsnip SerialData object.
53             @return SerialData containing serializable form of request. */
54         virtual Parsnip::SerialData retrieveRequestMessage() const = 0;
55 
56         /** Decode a response message, already converted to Parsnip SerialData,
57             into some internal representation.
58             @param message The message to be decoded. */
59         virtual void extractResponse (const Parsnip::SerialData &message) const = 0;
60     };
61 
62     /// Pandora request class.  A request whose response is empty/unimportant.
63     class Notification : public Request {
64     protected:
65         Notification (Source *src, const char *ep);
66         virtual void extractResponse (const Parsnip::SerialData &message) const override;
67     };
68 
69     /// Pandora message: Retrieve version number.  We use this as a no-op.
70     class RetrieveVersionRequest : public Request {
71         mutable int result;
72 
73     public:
74         RetrieveVersionRequest (Source *src);
75         virtual Parsnip::SerialData retrieveRequestMessage() const override;
76         virtual void extractResponse (const Parsnip::SerialData &message) const override;
77         inline const int getResult() const {
78             return result;
79         }
80     };
81 
82     /// Pandora message: Retrieve station list
83     class RequestStationList : public Request {
84         mutable std::unique_ptr<PlaylistList> results;
85 
86     public:
87         RequestStationList (Source *src);
88         virtual Parsnip::SerialData retrieveRequestMessage() const override;
89         virtual void extractResponse (const Parsnip::SerialData &message) const override;
90         inline const PlaylistList &getResponse() const {
91             assert (results);
92             return *results;
93         }
94     };
95 
96     /// Pandora message: create a station
97     class RequestCreateStation : public Request {
98         std::string name;
99         std::string create_from_id;
100         mutable Station *result{nullptr};
101 
102     public:
103         RequestCreateStation (Source *src, const std::string &name, const std::string &creator_pandora_id);
104         virtual Parsnip::SerialData retrieveRequestMessage() const override;
105         virtual void extractResponse (const Parsnip::SerialData &message) const override;
106         inline Station *getResponse() const {
107             assert (result);
108             return result;
109         }
110     };
111 
112     /// Pandora message: delete a station
113     class RequestRemoveStation : public Request {
114         std::string station_id;
115 
116     public:
117         RequestRemoveStation (Source *src, Station *station);
118         virtual Parsnip::SerialData retrieveRequestMessage() const override;
119         virtual void extractResponse (const Parsnip::SerialData &message) const override;
120     };
121 
122     /// Pandora message: transform a shared station into a personal station
123     class RequestTransformStation : public Request {
124         std::string station_id;
125         mutable Station *updated_info{nullptr};
126 
127     public:
128         RequestTransformStation (Source *src, Station *station);
129         virtual Parsnip::SerialData retrieveRequestMessage() const override;
130         virtual void extractResponse (const Parsnip::SerialData &message) const override;
131         inline const Station *getUpdatedStation() const {
132             assert (updated_info);
133             return updated_info;
134         }
135     };
136 
137     /// Pandora message: rename a station
138     class RequestRenameStation : public Request {
139         std::string station_id;
140         std::string name;
141 
142     public:
143         RequestRenameStation (Source *src, Station *station, const std::string &new_name);
144         virtual Parsnip::SerialData retrieveRequestMessage() const override;
145         virtual void extractResponse (const Parsnip::SerialData &message) const override;
146     };
147 
148     /// Pandora message: Retrieve station seeds
149     class RequestStationSeeds : public Request {
150     protected:
151         std::string station_id;
152         mutable std::unique_ptr<ThingieList> seeds;
153         MusicThingie *extractAssortedSeed (const Parsnip::SerialData &seed_info) const;
154         RequestStationSeeds (Source *src, const char *endpoint, Station *station);
155 
156     public:
157         RequestStationSeeds (Source *src, Station *station);
158         virtual Parsnip::SerialData retrieveRequestMessage() const override;
159         virtual void extractResponse (const Parsnip::SerialData &message) const override;
160         inline const ThingieList &getSeeds() const {
161             assert (seeds);
162             return *seeds;
163         }
164     };
165 
166     /// Pandora message: Retrieve station details (seeds and a few other goodies)
167     class RequestStationDetails : public RequestStationSeeds {
168         mutable int positive_feedback{-1};
169         mutable int negative_feedback{-1};
170 
171     public:
172         RequestStationDetails (Source *src, Station *station);
173         virtual Parsnip::SerialData retrieveRequestMessage() const override;
174         virtual void extractResponse (const Parsnip::SerialData &message) const override;
175         inline const bool positiveFeedback() const {
176             assert (positive_feedback >= 0);
177             return positive_feedback;
178         }
179         inline const bool negativeFeedback() const {
180             assert (negative_feedback >= 0);
181             return negative_feedback;
182         }
183     };
184 
185     /// Pandora message: Add or remove station seeds
186     class RequestAlterStationSeed : public Request {
187         std::string station_id;
188         std::string seed_id;
189 
190     public:
191         RequestAlterStationSeed (Source *src, Station *station, const std::string &id, bool add);
192         virtual Parsnip::SerialData retrieveRequestMessage() const override;
193         virtual void extractResponse (const Parsnip::SerialData &message) const override;
194     };
195 
196     /// Pandora message: Retrieve station feedback (ratings)
197     class RequestStationFeedback : public Request {
198         std::string station_id;
199         bool positive;
200         mutable std::unique_ptr<SongList> results;
201 
202     public:
203         RequestStationFeedback (Source *src, Station *station, bool positive);
204         virtual Parsnip::SerialData retrieveRequestMessage() const override;
205         virtual void extractResponse (const Parsnip::SerialData &message) const override;
206         inline const SongList &getResponse() const {
207             assert (results);
208             return *results;
209         }
210     };
211 
212     /// Pandora message: Provide feedback for a song on a station.
213     class RequestAddTiredSong : public Request {
214         const std::string track_token;
215 
216     public:
217         RequestAddTiredSong (Source *src, const std::string &token);
218         virtual Parsnip::SerialData retrieveRequestMessage() const override;
219         virtual void extractResponse (const Parsnip::SerialData &message) const override;
220     };
221 
222     /// Pandora message: Provide feedback for a song that has played on a station.
223     class RequestAddFeedback : public Request {
224         const std::string track_token;
225         const bool positive;
226         mutable std::unique_ptr<std::string> feedback_id;
227 
228     public:
229         RequestAddFeedback (Source *src, const std::string &token, bool like);
230         virtual Parsnip::SerialData retrieveRequestMessage() const override;
231         virtual void extractResponse (const Parsnip::SerialData &message) const override;
232         inline const std::string &getResponse() const {
233             assert (feedback_id);
234             return *feedback_id;
235         }
236     };
237 
238     /// Pandora message: Remove feedback for a song on a station.
239     class RequestDeleteFeedback : public Request {
240         const std::string feedback_id;
241         const bool positive;
242 
243     public:
244         RequestDeleteFeedback (Source *src, const std::string &feedback, bool like);
245         virtual Parsnip::SerialData retrieveRequestMessage() const override;
246         virtual void extractResponse (const Parsnip::SerialData &message) const override;
247     };
248 
249     /// Pandora message: Retrieve list of music to play from a station.
250     class RequestQueueTracks : public Request {
251         const std::string station_id;
252         const PlayableSong *last_play;
253         mutable std::unique_ptr<SongList> results;
254 
255     public:
256         RequestQueueTracks (Source *src, const Station *station, const PlayableSong *last);
257         virtual Parsnip::SerialData retrieveRequestMessage() const override;
258         virtual void extractResponse (const Parsnip::SerialData &message) const override;
259         inline const SongList &getResponse() {
260             assert (results);
261             return *results;
262         }
263     };
264 
265     /// Pandora message: Retrieve list of music to play from a station.
266     class RequestTrackReplay : public Request {
267         const PlayableSong *request;
268         const PlayableSong *last_played;
269         mutable PlayableSong *result;
270     public:
271         RequestTrackReplay (Source *src, const PlayableSong *song, const PlayableSong *current);
272         virtual Parsnip::SerialData retrieveRequestMessage() const override;
273         virtual void extractResponse (const Parsnip::SerialData &message) const override;
274         inline PlayableSong *getResponse() {
275             assert (result);
276             return result;
277         }
278     };
279 
280     /// Pandora message: Notify servers of playback start
281     class PlaybackStartNotification : public Notification {
282         std::string track_token;
283 
284     public:
285         PlaybackStartNotification (Source *src, const PlayableSong *song);
286         virtual Parsnip::SerialData retrieveRequestMessage() const override;
287     };
288 
289     /// Pandora message: Notify servers of pausing playback
290     class PlaybackPauseNotification : public Notification {
291     public:
292         PlaybackPauseNotification (Source *src, const PlayableSong * = nullptr);
293         virtual Parsnip::SerialData retrieveRequestMessage() const override;
294     };
295 
296     /// Pandora message: Notify servers of playback resumption
297     class PlaybackResumedNotification : public Notification {
298     public:
299         PlaybackResumedNotification (Source *src, const PlayableSong * = nullptr);
300         virtual Parsnip::SerialData retrieveRequestMessage() const override;
301     };
302 
303     // Pandora message: Search request.
304     class SearchRequest : public Request {
305         std::string query;
306         std::string desired_type;
307         mutable std::unique_ptr<std::vector<std::string> > results;
308 
309     public:
310         static const std::string Type_ANY;
311         SearchRequest (Source *src, const std::string &q, const std::string &type = Type_ANY);
312         virtual Parsnip::SerialData retrieveRequestMessage() const override;
313         virtual void extractResponse (const Parsnip::SerialData &message) const override;
314         inline const std::vector<std::string> &getResponse() {
315             assert (results);
316             return *results;
317         }
318     };
319 
320     // Pandora message: retrieve details about songs, artists, albums, whatever.
321     class RetrieveAnnotations : public Request {
322         const std::vector<std::string> retrieval_items;
323 
324     protected:
325         mutable std::unique_ptr<ThingieList> results;
326 
327     public:
328         RetrieveAnnotations (Source *src, const std::vector<std::string> &items);
329         virtual Parsnip::SerialData retrieveRequestMessage() const override;
330         virtual void extractResponse (const Parsnip::SerialData &message) const override;
331         inline const ThingieList &getAnnotations() {
332             assert (results);
333             return *results;
334         }
335     };
336 
337     // Pandora message: retrieve details about a single song, artist, album, whatever.
338     class RetrieveSingleAnnotation : public RetrieveAnnotations {
339         const std::vector<std::string> retrieval_items;
340 
341     public:
342         RetrieveSingleAnnotation (Source *src, const std::string &item);
343         inline MusicThingie *getAnnotation() {
344             assert (results);
345             assert (results->size() == 1);
346             return (*results).front();
347         }
348     };
349 
350 
351     // Pandora message: retrieve advertisements.
352     class RetrieveAdverts : public Request {
353         PlayableSong *last_song;
354         Station *station;
355         mutable std::unique_ptr <SongList> adverts;
356     public:
357         RetrieveAdverts (Source *src, PlayableSong *last_play, Station *sta);
358         virtual Parsnip::SerialData retrieveRequestMessage() const override;
359         virtual void extractResponse (const Parsnip::SerialData &message) const override;
360         inline SongList &getAdverts () {
361             assert (adverts);
362             return *adverts;
363         }
364     };
365 }  // namespace Pandora
366