From 2da68bf9747a508e1bba9a79e2cb25e759ba8208 Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Mon, 14 Jun 2021 12:42:28 +0100 Subject: [PATCH 1/2] Update for jukebox extension readme removed the profit column showing 0 --- lnbits/extensions/jukebox/README.md | 35 +++++- lnbits/extensions/jukebox/static/js/index.js | 112 +++++++++---------- 2 files changed, 88 insertions(+), 59 deletions(-) diff --git a/lnbits/extensions/jukebox/README.md b/lnbits/extensions/jukebox/README.md index b92e7ea6..c761db44 100644 --- a/lnbits/extensions/jukebox/README.md +++ b/lnbits/extensions/jukebox/README.md @@ -1,5 +1,36 @@ # Jukebox -To use this extension you need a Spotify client ID and client secret. You get these by creating an app in the Spotify developers dashboard here https://developer.spotify.com/dashboard/applications +## An actual Jukebox where users pay sats to play their favourite music from your playlists -Select the playlists you want people to be able to pay for, share the frontend page, profit :) +**Note:** To use this extension you need a Premium Spotify subscription. + +## Usage + +1. Click on "ADD SPOTIFY JUKEBOX"\ + ![add jukebox](https://i.imgur.com/NdVoKXd.png) +2. Follow the steps required on the form\ + + - give your jukebox a name + - select a wallet to receive payment + - define the price a user must pay to select a song\ + ![pick wallet price](https://i.imgur.com/4bJ8mb9.png) + - follow the steps to get your Spotify App and get the client ID and secret key\ + ![spotify keys](https://i.imgur.com/w2EzFtB.png) + - paste the codes in the form\ + ![api keys](https://i.imgur.com/6b9xauo.png) + - copy the _Redirect URL_ presented on the form\ + ![redirect url](https://i.imgur.com/GMzl0lG.png) + - on Spotify click the "EDIT SETTINGS" button and paste the copied link in the _Redirect URI's_ prompt + ![spotify app setting](https://i.imgur.com/vb0x4Tl.png) + - back on LNBits, click "AUTORIZE ACCESS" and "Agree" on the page that will open + - choose on which device the LNBits Jukebox extensions will stream to, you may have to be logged in in order to select the device (browser, smartphone app, etc...) + - and select what playlist will be available for users to choose songs (you need to have already playlist on Spotify)\ + ![select playlists](https://i.imgur.com/g4dbtED.png) + +3. After Jukebox is created, click the icon to open the dialog with the shareable QR, open the Jukebox page, etc...\ + ![shareable jukebox](https://i.imgur.com/EAh9PI0.png) +4. The users will see the Jukebox page and choose a song from the selected playlist\ + ![select song](https://i.imgur.com/YYjeQAs.png) +5. After selecting a song they'd like to hear next a dialog will show presenting the music\ + ![play for sats](https://i.imgur.com/eEHl3o8.png) +6. After payment, the song will automatically start playing on the device selected or enter the queue if some other music is already playing diff --git a/lnbits/extensions/jukebox/static/js/index.js b/lnbits/extensions/jukebox/static/js/index.js index 57f9c678..1bf6ec4c 100644 --- a/lnbits/extensions/jukebox/static/js/index.js +++ b/lnbits/extensions/jukebox/static/js/index.js @@ -46,12 +46,6 @@ new Vue({ align: 'left', label: 'Price', field: 'price' - }, - { - name: 'profit', - align: 'left', - label: 'Profit', - field: 'profit' } ], pagination: { @@ -81,7 +75,7 @@ new Vue({ }, computed: {}, methods: { - openQrCodeDialog: function (linkId) { + openQrCodeDialog: function(linkId) { var link = _.findWhere(this.JukeboxLinks, {id: linkId}) this.qrCodeDialog.data = _.clone(link) @@ -93,8 +87,12 @@ new Vue({ getJukeboxes() { self = this LNbits.api - .request('GET', '/jukebox/api/v1/jukebox', self.g.user.wallets[0].adminkey) - .then(function (response) { + .request( + 'GET', + '/jukebox/api/v1/jukebox', + self.g.user.wallets[0].adminkey + ) + .then(function(response) { self.JukeboxLinks = response.data.map(mapJukebox) }) .catch(err => { @@ -105,15 +103,15 @@ new Vue({ self = this LNbits.utils .confirmDialog('Are you sure you want to delete this Jukebox?') - .onOk(function () { + .onOk(function() { LNbits.api .request( 'DELETE', '/jukebox/api/v1/jukebox/' + juke_id, self.g.user.wallets[0].adminkey ) - .then(function (response) { - self.JukeboxLinks = _.reject(self.JukeboxLinks, function (obj) { + .then(function(response) { + self.JukeboxLinks = _.reject(self.JukeboxLinks, function(obj) { return obj.id === juke_id }) }) @@ -123,7 +121,7 @@ new Vue({ }) }) }, - updateJukebox: function (linkId) { + updateJukebox: function(linkId) { self = this var link = _.findWhere(self.JukeboxLinks, {id: linkId}) self.jukeboxDialog.data = _.clone(link._data) @@ -165,10 +163,10 @@ new Vue({ LNbits.utils.notifyApiError(err) }) }, - authAccess() { + authAccess() { self = this - self.requestAuthorization() - self.getSpotifyTokens() + self.requestAuthorization() + self.getSpotifyTokens() self.$q.notify({ spinner: true, message: 'Processing', @@ -178,7 +176,7 @@ new Vue({ getSpotifyTokens() { self = this var counter = 0 - var timerId = setInterval(function () { + var timerId = setInterval(function() { counter++ if (!self.jukeboxDialog.data.sp_user) { clearInterval(timerId) @@ -195,37 +193,37 @@ new Vue({ if (self.jukeboxDialog.data.sp_access_token) { self.refreshPlaylists() self.refreshDevices() - console.log("this.devices") + console.log('this.devices') console.log(self.devices) - console.log("this.devices") - setTimeout(function () { - if (self.devices.length < 1 || self.playlists.length < 1) { - self.$q.notify({ - spinner: true, - color: 'red', - message: - 'Error! Make sure Spotify is open on the device you wish to use, has playlists, and is playing something', - timeout: 10000 - }) - LNbits.api - .request( - 'DELETE', - '/jukebox/api/v1/jukebox/' + response.data.id, - self.g.user.wallets[0].adminkey - ) - .then(function (response) { - self.getJukeboxes() + console.log('this.devices') + setTimeout(function() { + if (self.devices.length < 1 || self.playlists.length < 1) { + self.$q.notify({ + spinner: true, + color: 'red', + message: + 'Error! Make sure Spotify is open on the device you wish to use, has playlists, and is playing something', + timeout: 10000 }) - .catch(err => { - LNbits.utils.notifyApiError(err) - }) - clearInterval(timerId) - self.closeFormDialog() - } else { - self.step = 4 - clearInterval(timerId) - } - }, 2000) + LNbits.api + .request( + 'DELETE', + '/jukebox/api/v1/jukebox/' + response.data.id, + self.g.user.wallets[0].adminkey + ) + .then(function(response) { + self.getJukeboxes() + }) + .catch(err => { + LNbits.utils.notifyApiError(err) + }) + clearInterval(timerId) + self.closeFormDialog() + } else { + self.step = 4 + clearInterval(timerId) + } + }, 2000) } } }) @@ -269,7 +267,7 @@ new Vue({ self.g.user.wallets[0].adminkey, self.jukeboxDialog.data ) - .then(function (response) { + .then(function(response) { console.log(response.data) if ( self.jukeboxDialog.data.sp_playlists && @@ -290,7 +288,7 @@ new Vue({ 'Bearer ' + this.jukeboxDialog.data.sp_access_token ) xhr.send(body) - xhr.onload = function () { + xhr.onload = function() { if (xhr.status == 401) { self.refreshAccessToken() self.playlistApi( @@ -326,7 +324,7 @@ new Vue({ 'Bearer ' + this.jukeboxDialog.data.sp_access_token ) xhr.send(body) - xhr.onload = function () { + xhr.onload = function() { if (xhr.status == 401) { self.refreshAccessToken() self.deviceApi( @@ -347,15 +345,15 @@ new Vue({ } } }, - refreshDevices() { + refreshDevices() { self = this - self.deviceApi( + self.deviceApi( 'GET', 'https://api.spotify.com/v1/me/player/devices', null ) }, - fetchAccessToken(code) { + fetchAccessToken(code) { self = this let body = 'grant_type=authorization_code' body += '&code=' + code @@ -363,16 +361,16 @@ new Vue({ '&redirect_uri=' + encodeURI(self.locationcbPath + self.jukeboxDialog.data.sp_id) - self.callAuthorizationApi(body) + self.callAuthorizationApi(body) }, - refreshAccessToken() { + refreshAccessToken() { self = this let body = 'grant_type=refresh_token' body += '&refresh_token=' + self.jukeboxDialog.data.sp_refresh_token body += '&client_id=' + self.jukeboxDialog.data.sp_user - self.callAuthorizationApi(body) + self.callAuthorizationApi(body) }, - callAuthorizationApi(body) { + callAuthorizationApi(body) { self = this console.log( btoa( @@ -394,7 +392,7 @@ new Vue({ ) ) xhr.send(body) - xhr.onload = function () { + xhr.onload = function() { let responseObj = JSON.parse(xhr.response) if (responseObj.access_token) { self.jukeboxDialog.data.sp_access_token = responseObj.access_token From e2b18eb5a21879d3da07c92f0e2ef20dafcce8ac Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Fri, 18 Jun 2021 17:10:27 +0100 Subject: [PATCH 2/2] prettier fix? --- lnbits/extensions/jukebox/static/js/index.js | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lnbits/extensions/jukebox/static/js/index.js b/lnbits/extensions/jukebox/static/js/index.js index 1bf6ec4c..fc382d71 100644 --- a/lnbits/extensions/jukebox/static/js/index.js +++ b/lnbits/extensions/jukebox/static/js/index.js @@ -75,7 +75,7 @@ new Vue({ }, computed: {}, methods: { - openQrCodeDialog: function(linkId) { + openQrCodeDialog: function (linkId) { var link = _.findWhere(this.JukeboxLinks, {id: linkId}) this.qrCodeDialog.data = _.clone(link) @@ -92,7 +92,7 @@ new Vue({ '/jukebox/api/v1/jukebox', self.g.user.wallets[0].adminkey ) - .then(function(response) { + .then(function (response) { self.JukeboxLinks = response.data.map(mapJukebox) }) .catch(err => { @@ -103,15 +103,15 @@ new Vue({ self = this LNbits.utils .confirmDialog('Are you sure you want to delete this Jukebox?') - .onOk(function() { + .onOk(function () { LNbits.api .request( 'DELETE', '/jukebox/api/v1/jukebox/' + juke_id, self.g.user.wallets[0].adminkey ) - .then(function(response) { - self.JukeboxLinks = _.reject(self.JukeboxLinks, function(obj) { + .then(function (response) { + self.JukeboxLinks = _.reject(self.JukeboxLinks, function (obj) { return obj.id === juke_id }) }) @@ -121,7 +121,7 @@ new Vue({ }) }) }, - updateJukebox: function(linkId) { + updateJukebox: function (linkId) { self = this var link = _.findWhere(self.JukeboxLinks, {id: linkId}) self.jukeboxDialog.data = _.clone(link._data) @@ -176,7 +176,7 @@ new Vue({ getSpotifyTokens() { self = this var counter = 0 - var timerId = setInterval(function() { + var timerId = setInterval(function () { counter++ if (!self.jukeboxDialog.data.sp_user) { clearInterval(timerId) @@ -196,7 +196,7 @@ new Vue({ console.log('this.devices') console.log(self.devices) console.log('this.devices') - setTimeout(function() { + setTimeout(function () { if (self.devices.length < 1 || self.playlists.length < 1) { self.$q.notify({ spinner: true, @@ -211,7 +211,7 @@ new Vue({ '/jukebox/api/v1/jukebox/' + response.data.id, self.g.user.wallets[0].adminkey ) - .then(function(response) { + .then(function (response) { self.getJukeboxes() }) .catch(err => { @@ -267,7 +267,7 @@ new Vue({ self.g.user.wallets[0].adminkey, self.jukeboxDialog.data ) - .then(function(response) { + .then(function (response) { console.log(response.data) if ( self.jukeboxDialog.data.sp_playlists && @@ -288,7 +288,7 @@ new Vue({ 'Bearer ' + this.jukeboxDialog.data.sp_access_token ) xhr.send(body) - xhr.onload = function() { + xhr.onload = function () { if (xhr.status == 401) { self.refreshAccessToken() self.playlistApi( @@ -324,7 +324,7 @@ new Vue({ 'Bearer ' + this.jukeboxDialog.data.sp_access_token ) xhr.send(body) - xhr.onload = function() { + xhr.onload = function () { if (xhr.status == 401) { self.refreshAccessToken() self.deviceApi( @@ -392,7 +392,7 @@ new Vue({ ) ) xhr.send(body) - xhr.onload = function() { + xhr.onload = function () { let responseObj = JSON.parse(xhr.response) if (responseObj.access_token) { self.jukeboxDialog.data.sp_access_token = responseObj.access_token