lastfm_edit/
edit.rs

1/// Represents a scrobble edit operation.
2///
3/// This structure contains all the information needed to edit a specific scrobble
4/// on Last.fm, including both the original and new metadata values.
5///
6/// # Examples
7///
8/// ```rust
9/// use lastfm_edit::ScrobbleEdit;
10///
11/// // Create an edit to fix a track name
12/// let edit = ScrobbleEdit::from_track_info(
13///     "Paranoid Andriod", // original (misspelled)
14///     "OK Computer",
15///     "Radiohead",
16///     1640995200
17/// )
18/// .with_track_name("Paranoid Android"); // corrected
19///
20/// // Create an edit to change artist name
21/// let edit = ScrobbleEdit::from_track_info(
22///     "Creep",
23///     "Pablo Honey",
24///     "Radio Head", // original (wrong)
25///     1640995200
26/// )
27/// .with_artist_name("Radiohead") // corrected
28/// .with_edit_all(true); // update all instances
29/// ```
30#[derive(Debug, Clone)]
31pub struct ScrobbleEdit {
32    /// Original track name as it appears in the scrobble
33    /// If None, the client will attempt to look up the complete original metadata
34    pub track_name_original: Option<String>,
35    /// Original album name as it appears in the scrobble  
36    /// If None, the client will attempt to look up the complete original metadata
37    pub album_name_original: Option<String>,
38    /// Original artist name as it appears in the scrobble
39    /// If None, the client will attempt to look up the complete original metadata
40    pub artist_name_original: Option<String>,
41    /// Original album artist name as it appears in the scrobble
42    /// If None, the client will attempt to look up the complete original metadata
43    pub album_artist_name_original: Option<String>,
44
45    /// New track name to set
46    pub track_name: String,
47    /// New album name to set
48    pub album_name: String,
49    /// New artist name to set
50    pub artist_name: String,
51    /// New album artist name to set
52    pub album_artist_name: String,
53
54    /// Unix timestamp of the scrobble to edit
55    ///
56    /// This identifies the specific scrobble instance to modify.
57    pub timestamp: u64,
58    /// Whether to edit all instances or just this specific scrobble
59    ///
60    /// When `true`, Last.fm will update all scrobbles with matching metadata.
61    /// When `false`, only this specific scrobble (identified by timestamp) is updated.
62    pub edit_all: bool,
63}
64
65/// Response from a scrobble edit operation.
66///
67/// This structure contains the result of attempting to edit a scrobble,
68/// including success status and any error messages.
69///
70/// # Examples
71///
72/// ```rust
73/// use lastfm_edit::EditResponse;
74///
75/// let response = EditResponse {
76///     success: true,
77///     message: Some("Track name updated successfully".to_string()),
78/// };
79///
80/// if response.success {
81///     println!("Edit succeeded: {}", response.message.unwrap_or_default());
82/// } else {
83///     eprintln!("Edit failed: {}", response.message.unwrap_or_default());
84/// }
85/// ```
86#[derive(Debug)]
87pub struct EditResponse {
88    /// Whether the edit operation was successful
89    pub success: bool,
90    /// Optional message describing the result or any errors
91    pub message: Option<String>,
92}
93
94impl ScrobbleEdit {
95    /// Create a new [`ScrobbleEdit`] with all required fields.
96    ///
97    /// This is the most general constructor that allows setting all fields.
98    /// For convenience, consider using [`from_track_info`](Self::from_track_info) instead.
99    ///
100    /// # Arguments
101    ///
102    /// * `track_name_original` - The current track name in the scrobble
103    /// * `album_name_original` - The current album name in the scrobble
104    /// * `artist_name_original` - The current artist name in the scrobble
105    /// * `album_artist_name_original` - The current album artist name in the scrobble
106    /// * `track_name` - The new track name to set
107    /// * `album_name` - The new album name to set
108    /// * `artist_name` - The new artist name to set
109    /// * `album_artist_name` - The new album artist name to set
110    /// * `timestamp` - Unix timestamp identifying the scrobble
111    /// * `edit_all` - Whether to edit all matching scrobbles or just this one
112    #[allow(clippy::too_many_arguments)]
113    pub fn new(
114        track_name_original: Option<String>,
115        album_name_original: Option<String>,
116        artist_name_original: Option<String>,
117        album_artist_name_original: Option<String>,
118        track_name: String,
119        album_name: String,
120        artist_name: String,
121        album_artist_name: String,
122        timestamp: u64,
123        edit_all: bool,
124    ) -> Self {
125        Self {
126            track_name_original,
127            album_name_original,
128            artist_name_original,
129            album_artist_name_original,
130            track_name,
131            album_name,
132            artist_name,
133            album_artist_name,
134            timestamp,
135            edit_all,
136        }
137    }
138
139    /// Create an edit request from track information (convenience constructor).
140    ///
141    /// This constructor creates a [`ScrobbleEdit`] with the new values initially
142    /// set to the same as the original values. Use the builder methods like
143    /// [`with_track_name`](Self::with_track_name) to specify what should be changed.
144    ///
145    /// # Arguments
146    ///
147    /// * `original_track` - The current track name
148    /// * `original_album` - The current album name
149    /// * `original_artist` - The current artist name
150    /// * `timestamp` - Unix timestamp identifying the scrobble
151    ///
152    /// # Examples
153    ///
154    /// ```rust
155    /// use lastfm_edit::ScrobbleEdit;
156    ///
157    /// let edit = ScrobbleEdit::from_track_info(
158    ///     "Highway to Hell",
159    ///     "Highway to Hell",
160    ///     "AC/DC",
161    ///     1640995200
162    /// )
163    /// .with_track_name("Highway to Hell (Remastered)");
164    /// ```
165    pub fn from_track_info(
166        original_track: &str,
167        original_album: &str,
168        original_artist: &str,
169        timestamp: u64,
170    ) -> Self {
171        Self::new(
172            Some(original_track.to_string()),
173            Some(original_album.to_string()),
174            Some(original_artist.to_string()),
175            Some(original_artist.to_string()), // album_artist defaults to artist
176            original_track.to_string(),
177            original_album.to_string(),
178            original_artist.to_string(),
179            original_artist.to_string(), // album_artist defaults to artist
180            timestamp,
181            false, // edit_all defaults to false
182        )
183    }
184
185    /// Set the new track name.
186    ///
187    /// # Examples
188    ///
189    /// ```rust
190    /// # use lastfm_edit::ScrobbleEdit;
191    /// let edit = ScrobbleEdit::from_track_info("Wrong Name", "Album", "Artist", 1640995200)
192    ///     .with_track_name("Correct Name");
193    /// ```
194    pub fn with_track_name(mut self, track_name: &str) -> Self {
195        self.track_name = track_name.to_string();
196        self
197    }
198
199    /// Set the new album name.
200    ///
201    /// # Examples
202    ///
203    /// ```rust
204    /// # use lastfm_edit::ScrobbleEdit;
205    /// let edit = ScrobbleEdit::from_track_info("Track", "Wrong Album", "Artist", 1640995200)
206    ///     .with_album_name("Correct Album");
207    /// ```
208    pub fn with_album_name(mut self, album_name: &str) -> Self {
209        self.album_name = album_name.to_string();
210        self
211    }
212
213    /// Set the new artist name.
214    ///
215    /// This also sets the album artist name to the same value.
216    ///
217    /// # Examples
218    ///
219    /// ```rust
220    /// # use lastfm_edit::ScrobbleEdit;
221    /// let edit = ScrobbleEdit::from_track_info("Track", "Album", "Wrong Artist", 1640995200)
222    ///     .with_artist_name("Correct Artist");
223    /// ```
224    pub fn with_artist_name(mut self, artist_name: &str) -> Self {
225        self.artist_name = artist_name.to_string();
226        self.album_artist_name = artist_name.to_string();
227        self
228    }
229
230    /// Set whether to edit all instances of this track.
231    ///
232    /// When `true`, Last.fm will update all scrobbles with the same metadata.
233    /// When `false` (default), only the specific scrobble is updated.
234    ///
235    /// # Examples
236    ///
237    /// ```rust
238    /// # use lastfm_edit::ScrobbleEdit;
239    /// let edit = ScrobbleEdit::from_track_info("Track", "Album", "Artist", 1640995200)
240    ///     .with_track_name("New Name")
241    ///     .with_edit_all(true); // Update all instances
242    /// ```
243    pub fn with_edit_all(mut self, edit_all: bool) -> Self {
244        self.edit_all = edit_all;
245        self
246    }
247
248    /// Create an edit request with minimal information, letting the client look up missing metadata.
249    ///
250    /// This constructor is useful when you only know some of the original metadata and want
251    /// the client to automatically fill in missing information by looking up the scrobble.
252    ///
253    /// # Arguments
254    ///
255    /// * `track_name` - The new track name to set
256    /// * `artist_name` - The new artist name to set
257    /// * `album_name` - The new album name to set
258    /// * `timestamp` - Unix timestamp identifying the scrobble
259    ///
260    /// # Examples
261    ///
262    /// ```rust
263    /// use lastfm_edit::ScrobbleEdit;
264    ///
265    /// // Create an edit where the client will look up original metadata
266    /// let edit = ScrobbleEdit::with_minimal_info(
267    ///     "Corrected Track Name",
268    ///     "Corrected Artist",
269    ///     "Corrected Album",
270    ///     1640995200
271    /// );
272    /// ```
273    pub fn with_minimal_info(
274        track_name: &str,
275        artist_name: &str,
276        album_name: &str,
277        timestamp: u64,
278    ) -> Self {
279        Self::new(
280            None, // Client will look up original track name
281            None, // Client will look up original album name
282            None, // Client will look up original artist name
283            None, // Client will look up original album artist name
284            track_name.to_string(),
285            album_name.to_string(),
286            artist_name.to_string(),
287            artist_name.to_string(), // album_artist defaults to artist
288            timestamp,
289            false,
290        )
291    }
292}