Ver código fonte

Use new hm endpoint for playlists

HEnquist 5 anos atrás
pai
commit
e6295a6f9c

+ 4 - 6
examples/playlist_tracks.rs

@@ -18,7 +18,7 @@ use librespot::core::session::Session;
 use librespot::core::spotify_id::SpotifyId;
 use librespot::playback::config::PlayerConfig;
 use librespot::playback::config::Bitrate;
-use librespot::metadata::{FileFormat, Metadata, PlaylistMeta, Track, Album, Artist, Playlist};
+use librespot::metadata::{FileFormat, Metadata, Track, Album, Artist, Playlist};
 
 
 /*
@@ -60,15 +60,13 @@ fn main() {
     player_config.bitrate = Bitrate::Bitrate320;
 
     let args: Vec<_> = env::args().collect();
-    if args.len() != 5 {
-        println!("Usage: {} USERNAME PASSWORD PLAYLIST PLISTUSER", args[0]);
+    if args.len() != 4 {
+        println!("Usage: {} USERNAME PASSWORD PLAYLIST", args[0]);
     }
     let username = args[1].to_owned();
     let password = args[2].to_owned();
     let credentials = Credentials::with_password(username, password);
 
-    let plist_owner = args[4].to_string();
-
     let mut uri_split = args[3].split(":");
     let uri_parts: Vec<&str> = uri_split.collect();
     println!("{}, {}, {}",uri_parts[0], uri_parts[1], uri_parts[2]);
@@ -79,7 +77,7 @@ fn main() {
         .run(Session::connect(session_config, credentials, None, handle))
         .unwrap();
 
-    let plist = core.run(Playlist::get(&session, plist_uri, plist_owner, 0, 100)).unwrap();
+    let plist = core.run(Playlist::get(&session, plist_uri)).unwrap();
     println!("{:?}",plist);
     for track_id in plist.tracks {
         let plist_track = core.run(Track::get(&session, track_id)).unwrap();

+ 18 - 4
metadata/src/lib.rs

@@ -154,7 +154,8 @@ pub trait PlaylistMeta: Send + Sized + 'static {
 
     fn get(session: &Session, id: SpotifyId, user: String, start: i32, len: i32) -> Box<Future<Item = Self, Error = MercuryError>> {
         //let uri = format!("hm://playlist/{}?from={}&length={}",id.to_base62(), 0, 100);
-        let uri = format!("hm://playlist/user/{}/playlist/{}?from={}&length={}", user, id.to_base62(), start, len);
+        //let uri = format!("hm://playlist/user/{}/playlist/{}?from={}&length={}", user, id.to_base62(), start, len);
+        let uri = format!("hm://playlist/v2/playlist/{}", id.to_base62());
         println!("request uri: {}", uri);
         let request = session.mercury().get(uri);
         println!("a");
@@ -215,7 +216,7 @@ pub struct Show {
 
 #[derive(Debug, Clone)]
 pub struct Playlist {
-    //pub id: SpotifyId,
+    pub user: String,
     pub length: i32,
     pub name: String,
     pub tracks: Vec<SpotifyId>,
@@ -318,13 +319,25 @@ impl Metadata for Album {
     }
 }
 
-impl PlaylistMeta for Playlist {
+impl Metadata for Playlist {
     type Message = protocol::playlist4changes::SelectedListContent;
 
     fn base_url() -> &'static str {
-        "hm://playlist/'?from=' + from + '&length=' + length"
+        "hm://playlist/v2/playlist"
     }
 
+    fn get(session: &Session, id: SpotifyId) -> Box<Future<Item = Self, Error = MercuryError>> {
+        let uri = format!("{}/{}", Self::base_url(), id.to_base62());
+        let request = session.mercury().get(uri);
+
+        let session = session.clone();
+        Box::new(request.and_then(move |response| {
+            let data = response.payload.first().expect("Empty payload");
+            let msg: Self::Message = protobuf::parse_from_bytes(data).unwrap();
+
+            Ok(Self::parse(&msg, &session))
+        }))
+    }
 
     fn parse(msg: &Self::Message, _: &Session) -> Self {
 
@@ -345,6 +358,7 @@ impl PlaylistMeta for Playlist {
             name: msg.get_attributes().get_name().to_owned(),
             length: msg.get_length(),
             tracks: tracks,
+            user: msg.get_owner_username().to_string(),
         }
     }
 }

+ 1 - 0
protocol/proto/playlist4changes.proto

@@ -71,6 +71,7 @@ message ListChanges {
 message SelectedListContent {
     optional bytes revision = 0x1;
     optional int32 length = 0x2;
+    optional string owner_username =0x10;
     optional ListAttributes attributes = 0x3;
     optional ListChecksum checksum = 0x4;
     optional ListItems contents = 0x5;

+ 64 - 11
protocol/src/playlist4changes.rs

@@ -2748,6 +2748,7 @@ pub struct SelectedListContent {
     // message fields
     revision: ::protobuf::SingularField<::std::vec::Vec<u8>>,
     length: ::std::option::Option<i32>,
+    owner_username: ::protobuf::SingularField<::std::string::String>,
     attributes: ::protobuf::SingularPtrField<super::playlist4meta::ListAttributes>,
     checksum: ::protobuf::SingularPtrField<super::playlist4meta::ListChecksum>,
     contents: ::protobuf::SingularPtrField<super::playlist4content::ListItems>,
@@ -2830,6 +2831,42 @@ impl SelectedListContent {
         self.length = ::std::option::Option::Some(v);
     }
 
+    // optional string owner_username = 16;
+
+
+    pub fn get_owner_username(&self) -> &str {
+        match self.owner_username.as_ref() {
+            Some(v) => &v,
+            None => "",
+        }
+    }
+    pub fn clear_owner_username(&mut self) {
+        self.owner_username.clear();
+    }
+
+    pub fn has_owner_username(&self) -> bool {
+        self.owner_username.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_owner_username(&mut self, v: ::std::string::String) {
+        self.owner_username = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_owner_username(&mut self) -> &mut ::std::string::String {
+        if self.owner_username.is_none() {
+            self.owner_username.set_default();
+        }
+        self.owner_username.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_owner_username(&mut self) -> ::std::string::String {
+        self.owner_username.take().unwrap_or_else(|| ::std::string::String::new())
+    }
+
     // optional .ListAttributes attributes = 3;
 
 
@@ -3188,6 +3225,9 @@ impl ::protobuf::Message for SelectedListContent {
                     let tmp = is.read_int32()?;
                     self.length = ::std::option::Option::Some(tmp);
                 },
+                16 => {
+                    ::protobuf::rt::read_singular_string_into(wire_type, is, &mut self.owner_username)?;
+                },
                 3 => {
                     ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.attributes)?;
                 },
@@ -3247,6 +3287,9 @@ impl ::protobuf::Message for SelectedListContent {
         if let Some(v) = self.length {
             my_size += ::protobuf::rt::value_size(2, v, ::protobuf::wire_format::WireTypeVarint);
         }
+        if let Some(ref v) = self.owner_username.as_ref() {
+            my_size += ::protobuf::rt::string_size(16, &v);
+        }
         if let Some(ref v) = self.attributes.as_ref() {
             let len = v.compute_size();
             my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
@@ -3299,6 +3342,9 @@ impl ::protobuf::Message for SelectedListContent {
         if let Some(v) = self.length {
             os.write_int32(2, v)?;
         }
+        if let Some(ref v) = self.owner_username.as_ref() {
+            os.write_string(16, &v)?;
+        }
         if let Some(ref v) = self.attributes.as_ref() {
             os.write_tag(3, ::protobuf::wire_format::WireTypeLengthDelimited)?;
             os.write_raw_varint32(v.get_cached_size())?;
@@ -3398,6 +3444,11 @@ impl ::protobuf::Message for SelectedListContent {
                     |m: &SelectedListContent| { &m.length },
                     |m: &mut SelectedListContent| { &mut m.length },
                 ));
+                fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                    "owner_username",
+                    |m: &SelectedListContent| { &m.owner_username },
+                    |m: &mut SelectedListContent| { &mut m.owner_username },
+                ));
                 fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<super::playlist4meta::ListAttributes>>(
                     "attributes",
                     |m: &SelectedListContent| { &m.attributes },
@@ -3477,6 +3528,7 @@ impl ::protobuf::Clear for SelectedListContent {
     fn clear(&mut self) {
         self.revision.clear();
         self.length = ::std::option::Option::None;
+        self.owner_username.clear();
         self.attributes.clear();
         self.checksum.clear();
         self.contents.clear();
@@ -3534,17 +3586,18 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     eltaB\0\x12\x20\n\x16wantResultingRevisions\x18\x03\x20\x01(\x08B\0\x12\
     \x18\n\x0ewantSyncResult\x18\x04\x20\x01(\x08B\0\x12\x19\n\x04dump\x18\
     \x05\x20\x01(\x0b2\t.ListDumpB\0\x12\x10\n\x06nonces\x18\x06\x20\x03(\
-    \x05B\0:\0\"\x87\x03\n\x13SelectedListContent\x12\x12\n\x08revision\x18\
-    \x01\x20\x01(\x0cB\0\x12\x10\n\x06length\x18\x02\x20\x01(\x05B\0\x12%\n\
-    \nattributes\x18\x03\x20\x01(\x0b2\x0f.ListAttributesB\0\x12!\n\x08check\
-    sum\x18\x04\x20\x01(\x0b2\r.ListChecksumB\0\x12\x1e\n\x08contents\x18\
-    \x05\x20\x01(\x0b2\n.ListItemsB\0\x12\x15\n\x04diff\x18\x06\x20\x01(\x0b\
-    2\x05.DiffB\0\x12\x1b\n\nsyncResult\x18\x07\x20\x01(\x0b2\x05.DiffB\0\
-    \x12\x1c\n\x12resultingRevisions\x18\x08\x20\x03(\x0cB\0\x12\x17\n\rmult\
-    ipleHeads\x18\t\x20\x01(\x08B\0\x12\x12\n\x08upToDate\x18\n\x20\x01(\x08\
-    B\0\x12-\n\rresolveAction\x18\x0c\x20\x03(\x0b2\x14.ClientResolveActionB\
-    \0\x12\x1e\n\x06issues\x18\r\x20\x03(\x0b2\x0c.ClientIssueB\0\x12\x10\n\
-    \x06nonces\x18\x0e\x20\x03(\x05B\0:\0B\0b\x06proto2\
+    \x05B\0:\0\"\xa1\x03\n\x13SelectedListContent\x12\x12\n\x08revision\x18\
+    \x01\x20\x01(\x0cB\0\x12\x10\n\x06length\x18\x02\x20\x01(\x05B\0\x12\x18\
+    \n\x0eowner_username\x18\x10\x20\x01(\tB\0\x12%\n\nattributes\x18\x03\
+    \x20\x01(\x0b2\x0f.ListAttributesB\0\x12!\n\x08checksum\x18\x04\x20\x01(\
+    \x0b2\r.ListChecksumB\0\x12\x1e\n\x08contents\x18\x05\x20\x01(\x0b2\n.Li\
+    stItemsB\0\x12\x15\n\x04diff\x18\x06\x20\x01(\x0b2\x05.DiffB\0\x12\x1b\n\
+    \nsyncResult\x18\x07\x20\x01(\x0b2\x05.DiffB\0\x12\x1c\n\x12resultingRev\
+    isions\x18\x08\x20\x03(\x0cB\0\x12\x17\n\rmultipleHeads\x18\t\x20\x01(\
+    \x08B\0\x12\x12\n\x08upToDate\x18\n\x20\x01(\x08B\0\x12-\n\rresolveActio\
+    n\x18\x0c\x20\x03(\x0b2\x14.ClientResolveActionB\0\x12\x1e\n\x06issues\
+    \x18\r\x20\x03(\x0b2\x0c.ClientIssueB\0\x12\x10\n\x06nonces\x18\x0e\x20\
+    \x03(\x05B\0:\0B\0b\x06proto2\
 ";
 
 static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {