spotify-connect-ws
Advanced tools
Comparing version 0.0.2 to 0.1.0
{ | ||
"name": "spotify-connect-ws", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"description": "A WebSockets solution for Spotify's Connect API made using socket.io.", | ||
"main": "index.js", | ||
"main": "lib", | ||
"module": "lib/index.js", | ||
"author": "Lawrence Holmes", | ||
@@ -10,7 +11,6 @@ "license": "MIT", | ||
"lint": "eslint .", | ||
"build": "yarn lint && babel -d ./build ./src" | ||
"build": "yarn lint && babel -d ./lib ./src", | ||
"watch": "babel -d ./lib ./src --watch" | ||
}, | ||
"dependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"node-fetch": "^1.7.3" | ||
@@ -20,2 +20,4 @@ }, | ||
"babel-cli": "^6.26.0", | ||
"babel-core": "^6.26.0", | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"babel-preset-env": "^1.6.1", | ||
@@ -22,0 +24,0 @@ "eslint": "^4.10.0", |
@@ -8,3 +8,3 @@ WebSockets for Spotify Connect API | ||
It should be noted that this project does not fully solve the problems discussed in [this issue](#), in that there is still polling taking place (one request per second right now) and therefore hitting rate limits is a possibility. | ||
It should be noted that this project does not fully solve the problems discussed in [this issue](https://github.com/spotify/web-api/issues/492), in that there is still polling taking place (one request per second right now) and therefore hitting rate limits is a possibility. | ||
@@ -17,2 +17,4 @@ ### Important Note | ||
If you want to skip the server setup and go straight to working with your app, use this testing url in the meantime: https://spotify-connect-ws.herokuapp.com/connect | ||
Server: | ||
@@ -48,2 +50,4 @@ ```bash | ||
const io = openSocket('/connect') | ||
// or if using testing url | ||
const io = openSocket('https://spotify-connect-ws.herokuapp.com/connect') | ||
@@ -50,0 +54,0 @@ io.emit('initiate', { accessToken: 'access token' }) |
@@ -1,3 +0,1 @@ | ||
require('babel-core/register') | ||
module.exports = require('./socket') |
@@ -13,3 +13,6 @@ import { | ||
const C = { | ||
CONNECT_ERROR: 'connect_error' | ||
CONNECT_ERROR: 'connect_error', | ||
HAS_SCRUBBED_THRESHOLD: 1500, | ||
HAS_FINISHED_THRESHOLD: 2000, | ||
POLL_RATE: 1000 | ||
} | ||
@@ -30,2 +33,12 @@ | ||
const handleError = error => { | ||
const message = error.message || error | ||
if (message !== socket.lastSentError) { | ||
socket.emit(C.CONNECT_ERROR, error) | ||
socket.lastSentError = message | ||
} else { | ||
socket.pollRate = socket.pollRate < 5000 ? socket.pollRate + 1000 : 5000 | ||
} | ||
} | ||
socket.on('disconnect', () => { | ||
@@ -43,79 +56,87 @@ clearInterval(socket.poll) | ||
if (accessToken) { | ||
socket.accessToken = accessToken | ||
} | ||
socket.accessToken = accessToken | ||
socket.poll() | ||
}) | ||
socket.poll = () => { | ||
getPlayerState(socket.accessToken) | ||
.then(playerState => { | ||
socket.emit('initial_state', playerState) | ||
socket.playerState = playerState | ||
socket.poll = setInterval(() => { | ||
getPlayerState(socket.accessToken).then(playerState => { | ||
if (playerState.item.id !== socket.playerState.item.id) { | ||
// track has changed | ||
socket.emit('track_change', playerState.item) | ||
socket.hasNotifiedTrackEnd = false | ||
} else { | ||
// track is the same, check if it has been scrubbed | ||
if (playerState.is_playing) { | ||
const negativeProgress = | ||
playerState.progress_ms > | ||
socket.playerState.progress_ms + 1500 | ||
const positiveProgess = | ||
playerState.progress_ms < | ||
socket.playerState.progress_ms - 1500 | ||
if (negativeProgress || positiveProgess) { | ||
socket.emit( | ||
'seek', | ||
playerState.progress_ms, | ||
playerState.timestamp | ||
) | ||
} | ||
} | ||
} | ||
if (playerState.is_playing !== socket.playerState.is_playing) { | ||
// play state has changed | ||
const event = playerState.is_playing | ||
? 'playback_started' | ||
: 'playback_paused' | ||
socket.emit(event) | ||
} | ||
if (playerState.device.id !== socket.playerState.device.id) { | ||
// device has changed | ||
socket.emit('device_change', playerState.device) | ||
} else { | ||
// device is the same, check volume | ||
if ( | ||
playerState.device.volume_percent !== | ||
socket.playerState.device.volume_percent | ||
) { | ||
// device has changed | ||
socket.emit('volume_change', playerState.device.volume_percent) | ||
} | ||
} | ||
if (!playerState.device) { | ||
handleError('No active device') | ||
return | ||
} | ||
if (!socket.hasSentInitialState) { | ||
socket.emit('initial_state', playerState) | ||
socket.playerState = playerState | ||
socket.hasSentInitialState = true | ||
return | ||
} | ||
if ( | ||
!socket.hasNotifiedTrackEnd && | ||
playerState.progress_ms + 2000 > playerState.item.duration_ms | ||
) { | ||
socket.emit('track_end', playerState.item) | ||
socket.hasNotifiedTrackEnd = true | ||
// reset poll rate if no errors were encountered | ||
socket.pollRate = C.POLL_RATE | ||
if (playerState.item.id !== socket.playerState.item.id) { | ||
// track has changed | ||
socket.emit('track_change', playerState.item) | ||
socket.hasNotifiedTrackEnd = false | ||
} else { | ||
// track is the same, check if it has been scrubbed | ||
if (playerState.is_playing) { | ||
const negativeProgress = | ||
playerState.progress_ms > | ||
socket.playerState.progress_ms + C.HAS_SCRUBBED_THRESHOLD | ||
const positiveProgess = | ||
playerState.progress_ms < | ||
socket.playerState.progress_ms - C.HAS_SCRUBBED_THRESHOLD | ||
if (negativeProgress || positiveProgess) { | ||
socket.emit( | ||
'seek', | ||
playerState.progress_ms, | ||
playerState.timestamp | ||
) | ||
} | ||
} | ||
} | ||
if (playerState.is_playing !== socket.playerState.is_playing) { | ||
// play state has changed | ||
const event = playerState.is_playing | ||
? 'playback_started' | ||
: 'playback_paused' | ||
socket.emit(event) | ||
} | ||
if (playerState.device.id !== socket.playerState.device.id) { | ||
// device has changed | ||
socket.emit('device_change', playerState.device) | ||
} else { | ||
// device is the same, check volume | ||
if ( | ||
playerState.device.volume_percent !== | ||
socket.playerState.device.volume_percent | ||
) { | ||
// volume has changed | ||
socket.emit('volume_change', playerState.device.volume_percent) | ||
} | ||
} | ||
socket.playerState = playerState | ||
}) | ||
}, 1000) | ||
if ( | ||
!socket.hasNotifiedTrackEnd && | ||
playerState.progress_ms + C.HAS_FINISHED_THRESHOLD > | ||
playerState.item.duration_ms | ||
) { | ||
socket.emit('track_end', playerState.item) | ||
socket.hasNotifiedTrackEnd = true | ||
} | ||
socket.playerState = playerState | ||
}) | ||
.catch(e => socket.emit(C.CONNECT_ERROR, e)) | ||
}) | ||
.catch(handleError) | ||
setTimeout(socket.poll, socket.pollRate) | ||
} | ||
socket.on('play', track => { | ||
if (track) { | ||
playTrack(socket.accessToken, track).catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
playTrack(socket.accessToken, track).catch(handleError) | ||
} else { | ||
setPlayState(socket.accessToken, 'play').catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
setPlayState(socket.accessToken, 'play').catch(handleError) | ||
} | ||
@@ -125,23 +146,15 @@ }) | ||
socket.on('resume', () => { | ||
setPlayState(socket.accessToken, 'play').catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
setPlayState(socket.accessToken, 'play').catch(handleError) | ||
}) | ||
socket.on('pause', () => { | ||
setPlayState(socket.accessToken, 'pause').catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
setPlayState(socket.accessToken, 'pause').catch(handleError) | ||
}) | ||
socket.on('seek', positionMs => { | ||
seek(socket.accessToken, positionMs).catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
seek(socket.accessToken, positionMs).catch(handleError) | ||
}) | ||
socket.on('set_volume', volumePercent => { | ||
setVolume(socket.accessToken, volumePercent).catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
setVolume(socket.accessToken, volumePercent).catch(handleError) | ||
}) | ||
@@ -154,11 +167,7 @@ | ||
socket.on('previous_track', () => { | ||
previousTrack(socket.accessToken).catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
previousTrack(socket.accessToken).catch(handleError) | ||
}) | ||
socket.on('transfer_playback', device => { | ||
transferPlayback(socket.accessToken, device).catch(e => | ||
socket.emit(C.CONNECT_ERROR, e) | ||
) | ||
transferPlayback(socket.accessToken, device).catch(handleError) | ||
}) | ||
@@ -165,0 +174,0 @@ |
@@ -13,2 +13,8 @@ import fetch from 'node-fetch' | ||
}) | ||
.then(response => { | ||
if (response.status === 202) { | ||
return resolve({}) | ||
} | ||
return response | ||
}) | ||
.then(r => r.json()) | ||
@@ -15,0 +21,0 @@ .then(response => { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
111452
1
536
122
10
9
- Removedbabel-core@^6.26.0
- Removedansi-regex@2.1.1(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedbabel-code-frame@6.26.0(transitive)
- Removedbabel-core@6.26.3(transitive)
- Removedbabel-generator@6.26.1(transitive)
- Removedbabel-helpers@6.24.1(transitive)
- Removedbabel-messages@6.23.0(transitive)
- Removedbabel-plugin-syntax-object-rest-spread@6.13.0(transitive)
- Removedbabel-plugin-transform-object-rest-spread@6.26.0(transitive)
- Removedbabel-register@6.26.0(transitive)
- Removedbabel-runtime@6.26.0(transitive)
- Removedbabel-template@6.26.0(transitive)
- Removedbabel-traverse@6.26.0(transitive)
- Removedbabel-types@6.26.0(transitive)
- Removedbabylon@6.18.0(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedchalk@1.1.3(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedconvert-source-map@1.9.0(transitive)
- Removedcore-js@2.6.12(transitive)
- Removeddebug@2.6.9(transitive)
- Removeddetect-indent@4.0.0(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedesutils@2.0.3(transitive)
- Removedglobals@9.18.0(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedhome-or-tmp@2.0.0(transitive)
- Removedinvariant@2.2.4(transitive)
- Removedis-finite@1.1.0(transitive)
- Removedjs-tokens@3.0.2(transitive)
- Removedjsesc@1.3.0(transitive)
- Removedjson5@0.5.1(transitive)
- Removedlodash@4.17.21(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedms@2.0.0(transitive)
- Removedos-homedir@1.0.2(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedprivate@0.1.8(transitive)
- Removedregenerator-runtime@0.11.1(transitive)
- Removedrepeating@2.0.1(transitive)
- Removedslash@1.0.0(transitive)
- Removedsource-map@0.5.7(transitive)
- Removedsource-map-support@0.4.18(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedsupports-color@2.0.0(transitive)
- Removedto-fast-properties@1.0.3(transitive)
- Removedtrim-right@1.0.1(transitive)