-
Notifications
You must be signed in to change notification settings - Fork 17
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
Feature: Integrate Apple Music API #9
Comments
Won't implement. Musickit requires enrollment in the Developer program which costs $99 a year. Obnoxious 🙄 |
Hear me out, what if we set up a service that let's others use this API. So they would only have to login via the multi-scrobbler app, but it would use an API from an active dev account. I already pay the $99/year for a sub, and think it could benefit others. |
I'd be willing to do that. Biggest roadblock with this initially was that I couldn't even begin to develop & test this without the $99 upfront cost -- and I don't use apple music. If you'd be willing to lend me your credentials/developer token/whatever it is I need to develop this I would do it. Hit me up at multi@foxxmd.dev or on discord at FoxxMD#5986 if you're interested. |
I added you on Discord. Let's communicate there. |
Resources and requirements I've gathered so far... RequirementsRequired: Developer TokenTo generate need:
Using these credentials a JWT is created with kid/tid and signed with private key ( apple-music-token-node can be used as a convenience library to help create the token (takes care of all the JWT business, reading private key file, etc.) node-musickit-api can also do this and has personalization routes. Would be best to use just this library. Required: Music User TokenTo access personalized music content we must retrieve Music User Token (under Create a Music User Token heading) The only way I've found to do this so far is to use apple's MusicKit JS sdk. Unfortunately use of this library seems to be limited to browser-only. Which makes sense for user authorization but not helpful for post-auth server user. Some resources for use of musickit js:
Getting Recently Played TracksAPIThere is an simple API endpoint for recently played tracks NOTE: This is different from recently played resources which only returns grouped album/playlist/stations (reference) Header requires Authorization plus MusicKit JSMusicKit also contains a method for document.addEventListener('musickitloaded', function() {
// MusicKit global is now defined
MusicKit.configure({
developerToken: 'DEVELOPER-TOKEN',
app: {
name: 'My Cool Web App',
build: '1978.4.1'
}
});
let mu = MusicKit.getInstance();
mu.authorize().then(function(token) {
// token is music user token we should store for later
mu.api.recentPlayed()
});
}); Not ideal since it would require using pages served up by express in MS to get user token to begin with (see example in Community
node-musickit-api contains methods for personalized results but not ImplementationAt a low level gathering all the necessary info to get to the point where we can get recently played tracks would require:
Given MS already has 1-3 built and 4-5 will require tight integration with MS to ensure proper access control I don't think it makes sense to create a separate app as an api proxy. Instead this should be integrated in MS and an optional endpoint can be created to access the api flow if an MS operator so desires. |
Just published v2.1.0 which includes various personalized functions, but mainly, the ability to fetch recently played resources My package also handles JWT, so no need to stress about that, however it (yet) cannot generate user tokens as the Apple documentation on it is... well... for Swift (not really practical for NodeJS is it), so you will need to use MusicKit.js for the token. Documentation can be found on musickit.js.org |
Awesome thank you @Exerra ! One question..since node-musickit-api handles JWT can I get direct access to the resolved |
Hmm, didn't even think of this use case No, you can't. However I can make it so it gets exported in v2.1.1. Would you like me to do that? |
Yes please that would be hugely helpful. Or if possible export the method that creates the JWT so I can just do createDeveloperToken({
key: "",
teamId: "",
keyId: "",
}) and get the token back without having to initialize the whole thing |
Added it into the code, will validate if everything truly works and push v2.1.1 tommorow Also will send instructions on how to use the function :) |
thank you! |
v2.1.1 is published on NPM It fixed a major bug and also added the createJWT() function It needs the same parameters as the non-personalized constructor (key, teamid, keyId) // convert it to import if needed
const { createJWT } = require("node-musickit-api/modules/createJWT")
let token = createJWT({
key: "shjdfgdshj",
teamId: "32423",
keyId: "32g443"
}) |
perfect! thank you! |
I'm still working on this (haven't had much free time) but in the meantime there is a macOS application to scrobble from itunes to maloja, if this helps anyone. |
I've started looking into the /v1/me/recent/played/tracks API a bit, and it appears to have some pretty frustrating limitations:
|
@kelchm thanks for looking into this!
This isn't a huge issue. The subsonic api also has this issue so I implemented a simple state machine-esque source that keeps track of when a track is first seen through polling and doesn't scrobble it until its been seen for 30 seconds, among other things.
I'm not quite sure what you're saying here. So the api won't return results that are played from radio? Or it only returns a specific subset of your library? This is definitely a bigger issue. A general PSA for development requirements on apple music outside of the stuff listed above:
This is all just login using the generated URL from the apple music JS sdk. It's a huge hassle. I will be pushing a semi-working branch for apple music here soon if anyone wants to give it a try. The above reasons are why I haven't had much progress as of late. I am not an apple music subscriber so, along with the graciously provided developer credentials from @hmhrex I also need to borrow a friends laptop and phone to do any kind of development. 😩 |
Sorry, it seems that my initial understanding was partially incorrect. Here is my current understanding of the limitations: It appears that the history API does not report any tracks that are played via a radio station or "autoplay" (toggled at the top of the queue list). Any tracks that a user directly adds to the queue themselves will be reported. Example: if a user plays a song from an album, that song and all the following songs from that album are added to the queue and will be reported by the history api after they are played, even if they are not added to the user's library. If autoplay is turned on, Apple Music will automatically play similar music after the last song of the album completes and these tracks will not be reported via the history API. |
@FoxxMD you mind pushing up the in-progress branch (I'd like to take a stab at getting this implemented)? I subscribe to Apple Music and it would be nice to scrobble from it. A roundabout way I can achieve this is using multi-scrobbler to scrobble lastfm to maloja and use third-party apps on macOS and iOS to scrobble to lastfm. It'd be vastly easier to have multi-scrobbler use the music api. From what I understand, in order to work on this, I'll not only need an Apple Music sub, but I would need to upgrade my free dev account to a paid one right? ( why Apple??) |
@mariolopjr the
I don't know...definitely should give it a try with your free one first though! The quick start guide for node-musickit-api is a good starting point for what data you'll need and I have more details about those in requirements post above Using all the info you've gathered you'll create a file for MS in the [
{
"name": "aap",
"clients": ["myScrobblerClientName"],
"data": {
"keyId": "34B45GH",
"teamId": "123GF45BG",
"key": "/absolute/path/to/applePrivateKey.p8"
}
}
] After starting MS click on the authenticate link for the Apple source You'll get a mostly blank screen with one button that triggers auth init popup for the official musickit client If the login flow is successfully (you'll need to have your second device and 2FA stuff handy for the login) you will receive a user token in the callback at which point you should be able to initialize node-musickit-api and do whatever you want with it API-wise. Back when I posted in December I was able to get a token but then apple always returned a 500 for every endpoint i used the generated token on. I was not able to determine if there was something wrong with the auth flow I implemented or if it was something else...this is, unfortunately, as far as I could get. |
@FoxxMD awesome thanks!! Will take it for a spin and see what happens :D |
I no longer have access to an apple account that is paying for apple music so I cannot work on this. It also really does not seem feasible that anyone would want to implement it as it requires a developer account ($$$) to even use. I have updated the WorkaroundsIt's still possible to get scrobbles into MS via apple music! Or even straight into Maloja. However all of these solutions are on a per-device basis:
|
Hi, I would be interested in getting this implemented. I currently have a developer account sub (will expire in 12 months as I got it in December of 2023), and Apple Music, so it should be doable. How out-of-sync is the appleintegration branch? |
@samip5 you can use https://github.com/FoxxMD/multi-scrobbler/tree/appleDev branch which is now up to date with the The instructions from this comment #9 (comment) are still mostly accurate. At the "login to apple music" step from the above comment instead use the URL
substitute the token you got from the login flow developer console window. You can now uncomment these lines in If you can get that to actually work (recently played), the next steps would be:
|
Next issue is that it doesn't seem to actually use the |
Currently it seems to be an issue regarding source auth. How is it supposed to verify the creds? |
The path to the credentials file is set here and then if it exists is used to build the api client with all the necessary credentials here. You'll need to debug startup process and see why it isn't using your file (is the file name correct?). In Webstorm I debug using the npm script configuration like this and set a breakpoint on the lines I mentioned above. |
It is trying to use it but something about the authGate is returning undefined but doesn't return the unable to parse error, it just instead doesn't use it instead.. |
@FoxxMD The problem seems to be relevant at backend/sources/ScrobbleSources, line 529. The newSources.testAuth, has nothing, so it cannot verify the creds and thus fallback to as if it had none. There doesn't appear to be a way to verify creds: |
For now you could just check if the api client exists, in protected doAuthentication = async (): Promise<boolean> => {
return this.apiClient !== undefined;
} |
I did actually just check for the cred file instead. Current progress: samip5@3845cf8 GetRecentPlayes somewhat works:
How should it be handled that the response from Apple doesn't include any "playedAt" things? |
I would like to quickly jump in and reiterate something that I mentioned in Exerra/node-musickit-api#9 and that is that I no longer have have a paid Apple Dev account, so I cannot continue work on The code for the package to be honest isn't that good, mostly wrote it in a rush and it doesn't even have TS types (which probably has caused some pain) so I very much want to rewrite it, however I don't really wish to spend 99 USD just for one small package. TLDR: No support for |
More than pain because typing is missing entirely as a result. :( |
@samip5 nice work! I assume the song data looks like the response from this api documentation? Since there is no "played at" multi-scrobbler will have to guess (assume) that when a new song is found in the response data it was played shortly before it appeared. You can see it doing basically the same thing in @Exerra thank you again for your work! I'm aware your library is not being maintained but that's fine because IMO the number of people who will be using this integration will be 1) tiny given the $99/yr barrier and 2) requires so much setup for just one integration. This is and always will be a "beware of dragons" approach. EDIT: Ideally this integration gets close enough to useable that it entices samip, or someone else stumbling upon it, to improve both your library and this integration. When/if this gets merged into the main branch the documentation will heavily feature "this is not supported and you should not do this if you don't know what you are doing" language. |
Correct, and I think genres might be something that could be worthy to also track but not sure if it's implemented elsewhere either. |
I don't believe any of the scrobblers are designed to track genre but that would be nice. |
@FoxxMD 👋🏻 I'm not sure how much time I could devote to it but I'm not opposed to the idea — the biggest stumbling blocks I hit in that post remain though. Apple adding a timestamp to their response would make this a whole lot simpler (though it sounds like you may have that sorted in But yeah, I suppose not strictly opposed to getting brought up to speed and contributing. |
This right here is the why things are hard, that and idk what guy/gal decided to nuke the whole playlist modification endpoints that was there on the public API so you cant easily sync your playlists unless you do it manually in the apple music app 🙄 anyways if you guys every need MusicKit reg keys hit me up on discord since i have my apple dev account thats an org based one since it seems like the whole $99 a year thing is a barrier for a lot of peeps. dm on discord |
Apple Music implements a recently played api.
The text was updated successfully, but these errors were encountered: