Skip to content

Instantly share code, notes, and snippets.

@tomjaimz
Created April 21, 2021 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomjaimz/18c0e211ea979767ac7ac42640825e96 to your computer and use it in GitHub Desktop.
Save tomjaimz/18c0e211ea979767ac7ac42640825e96 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<script src="//sdk.scdn.co/spotify-player.js"></script>
</head>
<body>
<pre>Open Console</pre>
<script>
let token;
let sdkReady;
let player;
const name = `Minimal Anthem [${new Date.toISOString()}]`;
const ACTIONS = [
'connect',
'disconnect',
'getCurrentState',
'getVolume',
'pause',
'resume',
'togglePlay',
'previousTrack',
'nextTrack',
'transfer',
];
const EVENTS = [
'initialization_error',
'authentication_error',
'account_error',
'playback_error',
'player_state_changed',
'ready',
'not_ready',
];
const put = (url, body) =>
fetch(`https://api.spotify.com/v1/${url}`, {
method: 'PUT',
body: JSON.stringify(body),
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
const [
uriRow,
uriInput,
uriButton,
tokenRow,
tokenInput,
useToken,
getToken,
] = ['p', 'input', 'button', 'p', 'input', 'button', 'button'].map(
document.createElement
);
uriInput.placeholer = 'Enter URL or URI';
uriInput.id = 'uriInput';
uriButton.onclick = () => {
if (token.length !== 160) {
hint('no token');
return;
}
const inputValue = document.getElementById('uriInput').value;
const match = inputValue.match(
/https:\/\/open\.spotify\.com\/(.*)\/([^?]*)/
);
const [, type, id] = match ? match : inputValue.split(':');
const uri = `spotify:${type}:${id}`;
put(
`me/player/play`,
['track', 'episode'].includes(type)
? {uris: [uri]}
: {context_uri: uri}
);
};
uriButton.innerText = 'Play';
uriRow.append(uriInput, uriButton);
document.body.appendChild(uriRow);
tokenInput.placeholer = 'Enter Token';
tokenInput.id = 'tokenInput';
useToken.innerText = 'Use Token';
useToken.onclick = () => {
const tokenInput = document.getElementById('tokenInput').value;
if (tokenInput.value.length !== 160) {
hint('invalid token');
return;
}
token = tokenInput.value;
init();
};
getToken.onclick = () => {
window
.open(
'https://developer.spotify.com/documentation/web-playback-sdk/quick-start/',
'_blank'
)
.focus();
};
getToken.innerText = 'Get Token';
tokenRow.append(tokenInput, useToken, getToken);
document.body.appendChild(tokenRow);
const hint = (v) => {
setTimeout(() => {
console.log(
`Try %c${v}%c first`,
'font-weight: bold',
'font-weight: normal'
);
}, 0);
};
for (const action of ACTIONS) {
const button = document.createElement('button');
button.onclick = async () => {
if (token.length !== 160) {
hint('no token');
return;
}
if (!player) {
hint('player not ready');
return;
}
console.log(action, await player[action]());
};
button.innerText = action;
document.body.appendChild(button);
}
const init = async () => {
if (!sdkReady) return;
if (!token) return;
const player = new Spotify.Player({
name,
getOAuthToken: (fn) => fn(token),
});
player.transfer = async () => {
if (token.length !== 160) {
hint('no token');
return;
}
const {device_id} = player._options;
if (device_id) {
const response = await put('me/player', {device_ids: [device_id]});
if (response.status === 404) {
const {message} = await response.json();
if (message === 'Device not found') {
hint('connect');
}
}
} else {
hint('connect');
}
return device_id;
};
for (const event of EVENTS) {
player.addListener(`${event}`, (body) => {
if (event === 'ready') {
player._options.device_id = body.device_id;
}
if (
event === 'playback_error' &&
body.message === 'Cannot perform operation; no list was loaded.'
) {
hint('transfer');
}
console.log(event, body);
});
}
};
window.onSpotifyWebPlaybackSDKReady = () => {
sdkReady = true;
init();
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment