Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for playlists #656

Open
roosemberth opened this issue Mar 13, 2018 · 29 comments
Open

Support for playlists #656

roosemberth opened this issue Mar 13, 2018 · 29 comments

Comments

@roosemberth
Copy link

Is it possible to support playlists? (And maybe create a station from a playlist after it ends?).

@PromyLOPh
Copy link
Owner

PromyLOPh commented Mar 14, 2018 via email

@PromyLOPh
Copy link
Owner

Update on this issue: Playlists are supported my the mobile API (as expected). The following API calls are probobly relevant:

playlists.*
browse.*
pods.*

The issue I see here is that playlists won’t be useful without proper management interface and catalog browsing. And right now I don’t want to invest that much time into pianobar. So, if anyone want to do this: Go ahead, submit a pull request and we’ll work something out.

@sehrgut
Copy link

sehrgut commented Apr 30, 2018

Would you consider simply subscribing to playlists (by URI or ID), rather than full playlist management, to be in-scope? It's something I've been wanting as well, but don't think I care enough about playlist management/curation to implement more than that.

@PromyLOPh
Copy link
Owner

PromyLOPh commented Apr 30, 2018 via email

@sehrgut
Copy link

sehrgut commented May 1, 2018

Thanks! As long as you don't mind me taking about a month before I really have time to work on this, you can go ahead and assign it to me.

@PromyLOPh
Copy link
Owner

PromyLOPh commented May 2, 2018 via email

@sehrgut
Copy link

sehrgut commented May 2, 2018

Perfect. I'll just task this in my trello then!

@hathawayj
Copy link

Excited to see this feature.

@BeaverTek
Copy link

@sehrgut What ever happened with this?

@sehrgut
Copy link

sehrgut commented Feb 1, 2021

I stopped using Pandora.

@skiphansen
Copy link

Update on this issue: Playlists are supported my the mobile API (as expected). The following API calls are probobly relevant:

playlists.* browse.* pods.*

The issue I see here is that playlists won’t be useful without proper management interface and catalog browsing. And right now I don’t want to invest that much time into pianobar. So, if anyone want to do this: Go ahead, submit a pull request and we’ll work something out.

I'm interesting into pushing this forward at least to the point of being able play a manually entered playlist.

I've snipped the connection between my Android APP and Pandor's cloud while playing a playlist but all of the API comms are over a TLSV1.2 connection.

Any hints on how to get the plaintext? Do I need to play DNS games and run an TLS proxy?

@PromyLOPh
Copy link
Owner

I can’t tell you how to analyze the communication via sniffing. Looking at the APK is usually easier.

@skiphansen
Copy link

I've make a lot of progress in sniffing the API communications (thank you wireshark, chrome & SSLKEYLOGFILE!). I think I understand a lot of what I need to know. However I now that I've read https://6xq.net/pandora-apidoc/ I understand that there are two APIs and all I've been sniffing the REST API not the JSON API V5 that pianobar uses.

I also read that

The Pandora REST API is used by modern Pandora apps including the website and the various mobile apps provided by Pandora.

Does that mean that the APK you used is of an old app that's no longer distributed ?

What is the status of PromyLOPh/pandora-apidoc#45 in 2024 ? Is it hopeless? It seems like all new Pandora related development stopped 3 years ago?

@PromyLOPh
Copy link
Owner

The APKs I have are quite old, so it’s very likely they are not officially distributed any more. It looks like apkmirror.com has older versions though.

I don’t know the status of that ticket, because pianobar does not use the REST API and therefore does not have that problem.

@skiphansen
Copy link

@PromyLOPh Can you tell me what version of the app you based your research on?

@PromyLOPh
Copy link
Owner

Many, many versions from for example 1.5.14 to 6.3 to 8.5 to 1804.2 to 2007.1. Their versioning does not seem to be very stable over the years, so I can’t tell you which one is “newer”. In the versions I have ./com/pandora/radio/api/PublicApi.java is the code which talks to the (json) tuner API.

@skiphansen
Copy link

Thanks!

apkmirror doesn't have 2007.1, so I'll tied 1812.2. When I decompiled it with jadx I didn't find a ./com/pandora/radio/api/PublicApi.java, but I did find ./com/pandora/radio/api/x.java which I think is it (let's hear it for error logging!).

Onward...

@minecraftchest1
Copy link

I have the latest build off Playstore (version 2409.1) that I can share. Reach out via my contact information on my profile page.

You can also pull the APK directly off of any android device with developer mode enabled (does not require root) using ADB. Use adb shell pm path com.pandora.android to get the path to the APK, then adb pull <PATH> to pull the APK (remove the package: prefix from the path).

@skiphansen
Copy link

@minecraftchest1 Thanks, but I'm good with 1812.2.

I was looking for an older version that was as close to what PromyLOPh used as possible. From what I've read later versions switched to using the RESP API rather than the JSON V5 API that pianobar uses.

Reverse engineering the RESP API is much easier as javascript source code with comments are easily pulled from Pandora's web player. If panobar used the RESP API I'd probably be done already.

@skiphansen
Copy link

@PromyLOPh I've made some good progress reverse engineering the APIs I need to add support for playlists.

While I was there I also reverse engineered the podcast and album APIs.

My plan is to add a new mode concept with choices of station, playlist, podcast or albums.

Free users will have access to stations and podcasts. Subscription users with a will have access to playlists and premium subscription uses will have access to albums.

On startup pianobar would behave identically to the current code.

If the user selects a new mode pianobar would switch to the selected mode and play the selected station, podcast, playlist or album. Podcasts, playlists and albums have a finite length, once they have played to completion pianobar would return to station mode.

The default keyboard shortcut will be 'm'.

Does the approach sound reasonable?

@PromyLOPh
Copy link
Owner

What does playlist/podcast/album selection look like? I’m assuming playlists are owned by a user just like stations, so you’ll just list them; podcasts and albums probably need a search?

@skiphansen
Copy link

skiphansen commented Nov 2, 2024

A list of podcasts, playlists or albums is displayed from the user's "collection". Playlists are created by users and automatically by Pandora based on what Pandor thinks the user likes.

I'm NOT currently planning on adding support for "collecting", just support for playing items collected by the user using a standard Pandor App.

Searching for albums and podcasts and "collecting" could certainly be added.

So exactly the same as selecting a station, expect with a list of playlists, or podcasts or albums.

@PromyLOPh
Copy link
Owner

I see. Do you think it would be feasible to display all of those in a single list (the current “station list”) and using filters to narrow things down? Or would that be too messy?

@skiphansen
Copy link

Sure, that could work. I could add a "all" mode that would display everything.

@skiphansen
Copy link

skiphansen commented Nov 2, 2024

FYI: This is what my kludged up "station" list looks like currently:

         0) q   60's Hippie Band Radio
         1)   P 60's Hippie Band Radio Thumbs Up
         2) q   60s Oldies Radio
         3) q   60s Rock Radio
         4) q   60s, 70s, and 80s Hits Radio
         5) q   70s Funk Radio
         6)   P 70s Funk Radio Thumbs Up
         7) q   70s Pop Radio
         8) q   70s Remix Radio
         9) q   70s Rock Radio
        10) q   80s Dance Radio
        11) q   80s Pop Radio
        12) q   80s Rock Ballads Radio
        13) q   90s Dance Radio
        14) q   African Radio
        15) q   Artie Shaw & His Orchestra Radio
        16) q   Average White Band Radio
        17) q   aydio Radio
        18) q   Bach: Solo Piano
        19) q   Beach Bar Lounge Radio
        20)   P Best Synthesizer Soundtracks for Films
        21) q   Betrayal (Sorcerer Theme) Radio
        22) q   Blues Rock Radio
        23) q   Bob Dylan Radio
        24) q   Bob Marley Radio
        25) q   Bobby Womack Radio
        26) q   Boom Boom (2007 Remastered Version) Radio
        27) q   Brent Lewis Radio
        28) q   Brewer & Shipley Radio
        29) q   Cat Stevens Radio
        30) q   Celtic Radio
        31) q   Chicago Blues Radio
        32) q   Chris Stapleton Radio
        33) q   Christmas Choral Classics Radio
        34) q   Christmas Traditional Radio
        35) q   Classic Rock Radio
        36) q   Classical Guitar Radio
        37) q   Creedence Clearwater Revival Radio
        38) q   Crosby, Stills & Nash Radio
        39)   P Crosby, Stills & Nash Radio Thumbs Up
        40) q   Crosby, Stills, Nash & Young Radio
        41)   P Crosby, Stills, Nash & Young Radio Thumbs Up
        42) q   Delbert McClinton Radio
        43) q   Delta Blues Radio
        44) q   Dire Straits Radio
        45) q   Disco Radio
        46) q   Eagles Radio
        47)   P Electronic
        48) q   Eric Church Radio
        49) q   Eric Clapton Radio
        50) q   Evelyn "Champagne" King Radio
        51) q   Frightening Sounds Radio
        52) q   Gary Allan Radio
        53) q   Gary Moore Radio
        54)   P Gary Moore Radio Thumbs Up
        55) q   Gerry Rafferty Radio
        56) q   Gil Scott-Heron Radio
        57) q   Golden Oldies Radio
        58) q   Gordon Lightfoot Radio
        59) q   Halloween Party Radio
        60) q   Handpicked 100: Scary Shuffle Radio
        61) q   Hot Tuna Radio
        62) q   Instrumental Chill Radio
        63) q   Jackson Browne & David Lindley Radio
        64) q   Jackson Browne Radio
        65) q   James Taylor Radio
        66) q   Jamey Johnson Radio
        67) q   Joan Baez Radio
        68) q   Joe Bonamassa Radio
        69) q   John Williams (Classical Guitar) Radio
        70) q   Lenny Radio
        71) q   Lowrider Oldies Radio
        72) q   Meditation Radio
        73) q   Michael Jackson Radio
        74) q   Motown Radio
        75)   P My Thumbs Up
        76) q   Neil Young Radio
        77) q   New Age Instrumental Radio
        78) q   Nick Cave & The Bad Seeds Radio
        79) q   Nick Moss Band Radio
        80) q   Oldies Party Radio
        81)   P Oldies Party Radio Thumbs Up
        82) q   Paul Whiteman & His Orchestra Radio
        83) q   People Are Strange (Mono; 2017 Remaster) Radio
        84) q   Pharrell Williams Radio
        85) q   Pink Floyd Radio
        86)  Q  QuickMix
        87) q   Reggaeton Old School Radio
        88) q   Rock 'n' Roll Dad Radio
        89) q   Rock Hits Radio
        90) q   Santana Radio
        91) q   Scottish Traditional Radio
        92) q   Simon & Garfunkel Radio
        93) q   Smooth Jazz Instrumentals Radio
        94) q   Spooky Symphonies Radio
        95) q   St. Patrick's Day Radio
        96) q   Stevie Ray Vaughan Radio
        97) q   Sugar Ray Radio
        98) q   Taylor Swift Radio
        99) q   Teddy Pendergrass Radio
        100) q   Teena Marie Radio
        101) q   The Band Radio
        102) q   The Beatles Radio
        103) q   The Cambridge Singers (Holiday) Radio
        104) q   The Doobie Brothers Radio
        105) q   The Doors Radio
        106)   P The Drop
        107) q   The Glenn Miller Orchestra Radio
        108) q   The Kinks Radio
        109) q   The Mamas & The Papas Radio
        110) q   The Marshall Tucker Band Radio
        111) q   The Righteous Brothers Radio
        112) q   The Staple Singers Radio
        113)     Thumbprint Radio
        114)   P Top Dance Hits
        115) q   Van Morrison Radio
        116) q   Vom Himmel Hoch Radio
        117)   P Werewolf Music - Full Moon
        118) q   Whiskey Myers Radio
        119)   P Your Blues Soundtrack
        120)   P Your Classic Rock Soundtrack
        121)   P Your Focus Soundtrack
        122)   P Your Party Soundtrack
        123)   P Your Rock & Roll Soundtrack
[?] Select station:

And this is what the it looks like in playlist mode:

         0)   P 60's Hippie Band Radio Thumbs Up
         1)   P 70s Funk Radio Thumbs Up
         2)   P Best Synthesizer Soundtracks for Films
         3)   P Crosby, Stills & Nash Radio Thumbs Up
         4)   P Crosby, Stills, Nash & Young Radio Thumbs Up
         5)   P Electronic
         6)   P Gary Moore Radio Thumbs Up
         7)   P My Thumbs Up
         8)   P Oldies Party Radio Thumbs Up
         9)   P The Drop
        10)   P Top Dance Hits
        11)   P Werewolf Music - Full Moon
        12)   P Your Blues Soundtrack
        13)   P Your Classic Rock Soundtrack
        14)   P Your Focus Soundtrack
        15)   P Your Party Soundtrack
        16)   P Your Rock & Roll Soundtrack

P = playlist

@hacker1024
Copy link

@skiphansen

Sorry if I'm too late on this info, I've been busy with exams for the last few weeks.

Here's what I know about the JSON playlist API. I managed to play a playlist in my app a couple of years ago, but haven't really touched it since - though I don't think much has changed, looking at the latest official app.

Note

If I may toot my own horn for a second, I really do recommend my tool Pandora MITM for reverse-engineering the JSON API. I've been working on it in private for the past couple of years (I'm ripping out the base and turning it into a generic programmable MITM platform), but the current public version still works fine.

The API definitions detailed below all come straight from the inference plugin, which can generate Markdown among other things. These are approximations with a fairly low sample size, though.

There are two important API methods when it comes to playing a playlist:

playlists.v7.getTracks

This method returns the list of tracks in the given playlist.

Example call:

{
  "request": {
    "limit": 1000,
    "annotationLimit": 20,
    "pandoraId": "PL:123456789012345678:1234567890",
    "playlistVersion": 2,
    "bypassPrivacyRules": true
  }
}

Object

Field Type Optional Default
request JSON object No

request

Object

Field Type Optional Default
limit Integer No
annotationLimit Integer No
pandoraId String<Pandora ID> No
bypassPrivacyRules Boolean No
playlistVersion Integer Yes

Response

playlists.v7.getTracks

Object

Field Type Optional Default
notModified Boolean No
tracks List<JSON object> Yes
offset Integer Yes
annotations Map<String<Pandora ID>, Annotation> No
pandoraId String<Pandora ID> No
version Integer No
name String No
description String No
timeCreated Timestamp<Epoch<Milliseconds>> No
isPrivate Boolean No
secret Boolean No
linkedType String No
totalTracks Integer No
shareableUrlPath String No
thorLayers String No
duration Integer No
unlocked Boolean No
timeLastUpdated Timestamp<Epoch<Milliseconds>> No
viewerInfo JSON object No
autogenForListener Boolean No
listenerIdInfo JSON object No
includedTrackTypes List<Pandora type> No
collectible Boolean No
listenerId Integer No
listenerPandoraId String<Pandora ID> No
listenerIdToken String No

tracks

List

Field Type Optional Default
itemId Integer No
pandoraId String<Pandora ID> No
addedTimestamp Timestamp<Epoch<Milliseconds>> No
duration Integer No
trackPandoraId String<Pandora ID> No

viewerInfo

Object

Field Type Optional Default
editable Boolean No

listenerIdInfo

Object

Field Type Optional Default
listenerId Integer No
listenerPandoraId String<Pandora ID> No
listenerIdToken String No

onDemand.getAudioPlaybackInfo

This method is used to retrieve media URLs for a track.

Example call:

{
    "includeAudioToken": true,
    "pandoraId": "TR:12345678",
    "deviceCode": <v4 UUID from device registration>,
    "sourcePandoraId": "AU:12345:123456789012345678:1234567890",
}

The response is fairly self-explanatory. Some things to note:

  • The audio data from audioUrl is XOR-encrypted. The audioToken is repeated to match the file length.
  • I'm not sure if the trackGain has already been used in processing, or if that is the responsibility of the client.
  • The skip and receipt URLs are not mandatory, though I'm not sure how they effect recommendations.

Request

onDemand.getAudioPlaybackInfo

Object

Field Type Optional Default
includeAudioToken Boolean No
pandoraId String<Pandora ID> No
deviceCode String No
sourcePandoraId String<Pandora ID> No

Response

onDemand.getAudioPlaybackInfo

Object

Field Type Optional Default
audioSkipUrl String No
audioUrlMap JSON object No
trackGain String No
audioReceiptUrl String No

audioUrlMap

Object

Field Type Optional Default
highQuality JSON object No
mediumQuality JSON object No
lowQuality JSON object No

highQuality

Object

Field Type Optional Default
trackToken String No
audioToken String No
bitrate String No
encoding String No
audioUrl String No

mediumQuality

Object

Field Type Optional Default
trackToken String No
audioToken String No
bitrate String No
encoding String No
audioUrl String No

lowQuality

Object

Field Type Optional Default
trackToken String No
audioToken String No
bitrate String No
encoding String No
audioUrl String No

I hope this helps!
I'm free to chat on Matrix, Telegram or Discord too (my username is the same everywhere).

@skiphansen
Copy link

@hacker1024 Hi! I'm glad to see you are still around!

Your horn should be tooted, I've been looking at your code ... it's all very impressive!

I have been working on getting your pandora_mitm project working but I know NOTHING about Dart which has been holding me back a bit.

I also ran into a apktook issue trying to bypass certificate pining (iBotPeaches/Apktool#3718) with 2107.1 but it worked with 1812.2.

I have been able to play songs from playlists, albums and podcasts with hardcoded test code. I'm currently in the process of implementing them properly in pianobar.

I'm not happy with the way I'm enumerating albums and podcasts currently, it's very inefficient (using collections.v7.getItems and then catalog.v4.annotateObjects). I would like to sniff the official App to see what it does.

Any chance you can resurrect your https://crypto.epimetheus.tk/ ?

I'm a bit of a discord novice, what server do you hang out on? I'm Skip on the OpenEPaperLink discord channel (https://discord.com/invite/fekcBc5RN5).

@hacker1024
Copy link

The decryption tool is revived. It is available through its GitHub Pages URL.

@skiphansen
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants