mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-22 22:25:47 +01:00
removed display queue because spotify doesn't support
This commit is contained in:
parent
5052826bc2
commit
ba7bd91140
8 changed files with 128 additions and 158 deletions
|
@ -6,6 +6,7 @@ from lnbits.helpers import urlsafe_short_hash
|
|||
|
||||
|
||||
async def create_jukebox(
|
||||
inkey: str,
|
||||
user: str,
|
||||
wallet: str,
|
||||
title: str,
|
||||
|
@ -84,42 +85,7 @@ async def delete_jukebox(juke_id: str):
|
|||
async def create_jukebox_payment(
|
||||
song_id: str,
|
||||
payment_hash: str
|
||||
) -> Jukebox:
|
||||
result = await db.execute(
|
||||
"""
|
||||
INSERT INTO jukebox_payment (payment_hash, song_id, paid)
|
||||
VALUES (?, ?, ?)
|
||||
""",
|
||||
(
|
||||
payment_hash,
|
||||
song_id,
|
||||
False,
|
||||
),
|
||||
)
|
||||
jukebox_payment = await get_jukebox_payment(payment_hash)
|
||||
assert jukebox_payment, "Newly created Jukebox Payment couldn't be retrieved"
|
||||
return jukebox_payment
|
||||
|
||||
|
||||
async def update_jukebox_payment(payment_hash: str, **kwargs) -> Optional[JukeboxPayment]:
|
||||
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
||||
await db.execute(
|
||||
f"UPDATE jukebox_payment SET {q} WHERE payment_hash = ?", (*kwargs.values(), payment_hash)
|
||||
)
|
||||
return await get_jukebox_payment(payment_hash)
|
||||
|
||||
|
||||
async def get_jukebox_payment(payment_hash: str) -> Optional[JukeboxPayment]:
|
||||
row = await db.fetchone("SELECT * FROM jukebox_payment WHERE payment_hash = ?", (payment_hash,))
|
||||
return JukeboxPayment(**row) if row else None
|
||||
|
||||
|
||||
##################################SONGS QUEUED
|
||||
|
||||
async def create_jukebox_queue(
|
||||
song_id: str,
|
||||
payment_hash: str
|
||||
) -> Jukebox:
|
||||
) -> JukeboxPayment:
|
||||
result = await db.execute(
|
||||
"""
|
||||
INSERT INTO jukebox_payment (payment_hash, song_id, paid)
|
||||
|
|
|
@ -9,6 +9,7 @@ async def m001_initial(db):
|
|||
user TEXT,
|
||||
title TEXT,
|
||||
wallet TEXT,
|
||||
inkey TEXT,
|
||||
sp_user TEXT NOT NULL,
|
||||
sp_secret TEXT NOT NULL,
|
||||
sp_access_token TEXT,
|
||||
|
@ -32,16 +33,4 @@ async def m002_initial(db):
|
|||
paid BOOL
|
||||
);
|
||||
"""
|
||||
)
|
||||
async def m003_initial(db):
|
||||
"""
|
||||
Initial jukebox_queue table.
|
||||
"""
|
||||
await db.execute(
|
||||
"""
|
||||
CREATE TABLE jukebox_queue (
|
||||
jukebox_id TEXT PRIMARY KEY,
|
||||
queue TEXT
|
||||
);
|
||||
"""
|
||||
)
|
|
@ -12,6 +12,7 @@ class Jukebox(NamedTuple):
|
|||
user: str
|
||||
title: str
|
||||
wallet: str
|
||||
inkey: str
|
||||
sp_user: str
|
||||
sp_secret: str
|
||||
sp_access_token: str
|
||||
|
@ -32,12 +33,4 @@ class JukeboxPayment(NamedTuple):
|
|||
|
||||
@classmethod
|
||||
def from_row(cls, row: Row) -> "JukeboxPayment":
|
||||
return cls(**dict(row))
|
||||
|
||||
class JukeboxQueue(NamedTuple):
|
||||
jukebox_id: str
|
||||
queue: str
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, row: Row) -> "JukeboxQueue":
|
||||
return cls(**dict(row))
|
|
@ -168,12 +168,12 @@ new Vue({
|
|||
authAccess() {
|
||||
self = this
|
||||
self.requestAuthorization()
|
||||
self.getSpotifyTokens()
|
||||
self.$q.notify({
|
||||
spinner: true,
|
||||
message: 'Processing',
|
||||
timeout: 10000
|
||||
})
|
||||
self.getSpotifyTokens()
|
||||
},
|
||||
getSpotifyTokens() {
|
||||
self = this
|
||||
|
@ -195,6 +195,7 @@ new Vue({
|
|||
if (self.jukeboxDialog.data.sp_access_token) {
|
||||
self.refreshPlaylists()
|
||||
self.refreshDevices()
|
||||
setTimeout(function () {}, 2000)
|
||||
if (self.devices.length < 1 && self.playlists.length < 1) {
|
||||
self.$q.notify({
|
||||
spinner: true,
|
||||
|
@ -217,8 +218,7 @@ new Vue({
|
|||
})
|
||||
clearInterval(timerId)
|
||||
self.closeFormDialog()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
self.step = 4
|
||||
clearInterval(timerId)
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ new Vue({
|
|||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
}, 5000)
|
||||
}, 3000)
|
||||
},
|
||||
requestAuthorization() {
|
||||
self = this
|
||||
|
@ -267,9 +267,12 @@ new Vue({
|
|||
)
|
||||
.then(function (response) {
|
||||
console.log(response.data)
|
||||
if (self.jukeboxDialog.data.sp_playlists && self.jukeboxDialog.data.sp_devices) {
|
||||
if (
|
||||
self.jukeboxDialog.data.sp_playlists &&
|
||||
self.jukeboxDialog.data.sp_devices
|
||||
) {
|
||||
self.getJukeboxes()
|
||||
// self.JukeboxLinks.push(mapJukebox(response.data))
|
||||
// self.JukeboxLinks.push(mapJukebox(response.data))
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
|
@ -230,11 +230,20 @@
|
|||
<q-step :name="3" title="Add Redirect URI" icon="link" :done="step > 3">
|
||||
<img src="/jukebox/static/spotapi1.gif" />
|
||||
In the app go to edit-settings, set the redirect URI to this link
|
||||
<br /><small
|
||||
>{% raw %}{{ locationcb }}{{ jukeboxDialog.data.sp_id }}{% endraw
|
||||
%}</small
|
||||
<br /><q-btn
|
||||
dense
|
||||
outline
|
||||
unelevated
|
||||
color="green-7"
|
||||
size="xs"
|
||||
@click="copyText(locationcb + jukeboxDialog.data.sp_id, 'Link copied to clipboard!')"
|
||||
><small style="font-size: 60%"
|
||||
>{% raw %}{{ locationcb }}{{ jukeboxDialog.data.sp_id }}{% endraw
|
||||
%}</small
|
||||
><q-tooltip> Click to copy URL </q-tooltip></q-btn
|
||||
>
|
||||
Setting can be found
|
||||
<br />
|
||||
Settings can be found
|
||||
<a
|
||||
target="_blank"
|
||||
color="green-7"
|
||||
|
|
|
@ -6,15 +6,12 @@
|
|||
<p style="font-size: 22px">Currently playing</p>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<img style="width: 100px" :src="currentPlaylist[0].image" />
|
||||
<img style="width: 100px" :src="currentPlay.image" />
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<strong style="font-size: 20px"
|
||||
>{{ currentPlaylist[0].name }}</strong
|
||||
<strong style="font-size: 20px">{{ currentPlay.name }}</strong
|
||||
><br />
|
||||
<strong style="font-size: 15px"
|
||||
>{{ currentPlaylist[0].artist }}</strong
|
||||
>
|
||||
<strong style="font-size: 15px">{{ currentPlay.artist }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
@ -57,30 +54,7 @@
|
|||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-md-5 col-lg-4 q-gutter-y-md">
|
||||
<q-card class="q-pa-lg">
|
||||
<q-card-section class="q-pa-none">
|
||||
<p style="font-size: 21px">Queued</p>
|
||||
<br />
|
||||
<q-list bordered separator>
|
||||
<q-item
|
||||
bordered
|
||||
v-for="song in queued"
|
||||
:key="song.id"
|
||||
clickable
|
||||
v-ripple
|
||||
@click="payForSong(song.id, song.name, song.artist, song.image)"
|
||||
>
|
||||
<q-item-section prepend>
|
||||
<img style="width: 50px" :src="song.image" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>{{ song.name }} ({{ song.artist }})</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<q-dialog v-model="receive.dialogues.first" position="top">
|
||||
<q-card class="q-pa-lg lnbits__dialog-card">
|
||||
<q-card-section class="q-pa-none">
|
||||
|
@ -130,11 +104,15 @@
|
|||
mixins: [windowMixin],
|
||||
data() {
|
||||
return {
|
||||
currentPlaylist: {},
|
||||
currentPlaylist: [],
|
||||
currentlyPlaying: {},
|
||||
cancelListener: () => {},
|
||||
playlists: {},
|
||||
playlist: '',
|
||||
heavyList: [],
|
||||
queued: [],
|
||||
selectedWallet: {
|
||||
inkey: '{{ inkey }}'
|
||||
},
|
||||
receive: {
|
||||
dialogues: {
|
||||
first: false,
|
||||
|
@ -150,8 +128,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
computed: {
|
||||
currentPlay() {
|
||||
return this.currentlyPlaying
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
startPaymentNotifier() {
|
||||
this.cancelListener()
|
||||
this.cancelListener = LNbits.events.onInvoicePaid(
|
||||
this.selectedWallet,
|
||||
payment => console.log(payment)
|
||||
)
|
||||
},
|
||||
cancelPayment: function () {
|
||||
this.paymentReq = null
|
||||
clearInterval(this.paymentDialog.checker)
|
||||
|
@ -185,37 +174,24 @@
|
|||
self.receive.paymentReq = response.data[0][1]
|
||||
self.receive.paymentHash = response.data[0][0]
|
||||
self.receive.dialogues.second = true
|
||||
|
||||
pChecker = setInterval(function () {
|
||||
axios
|
||||
.get(
|
||||
'/jukebox/api/v1/jukebox/jb/invoicecheck/' +
|
||||
self.receive.paymentHash +
|
||||
'/{{ juke_id }}'
|
||||
)
|
||||
.then(function (res) {
|
||||
console.log(res.data)
|
||||
if (res.data.status == true) {
|
||||
console.log('pooooooo')
|
||||
// self.cancelPayment()
|
||||
clearInterval(pChecker)
|
||||
self.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Payment received!',
|
||||
icon: null
|
||||
})
|
||||
self.receive.dialogues.second = false
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
}, 5000)
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
},
|
||||
getCurrent() {
|
||||
axios
|
||||
.get('/jukebox/api/v1/jukebox/jb/currently/{{juke_id}}')
|
||||
.then(function (res) {
|
||||
if (res.data.id) {
|
||||
console.log(res.data)
|
||||
self.currentlyPlaying = res.data
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
selectPlaylist() {
|
||||
self = this
|
||||
LNbits.api
|
||||
|
@ -234,19 +210,14 @@
|
|||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
}
|
||||
},
|
||||
currentSong() {}
|
||||
},
|
||||
created() {
|
||||
this.getCurrent()
|
||||
this.playlists = JSON.parse('{{ playlists | tojson }}')
|
||||
|
||||
self = this
|
||||
console.log(
|
||||
'/jukebox/api/v1/jukebox/jb/' +
|
||||
'{{ juke_id }}' +
|
||||
'/' +
|
||||
self.playlists[0].split(',')[0].split('-')[1] +
|
||||
'/'
|
||||
)
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
|
@ -263,6 +234,7 @@
|
|||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
})
|
||||
this.startPaymentNotifier()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -29,7 +29,8 @@ async def print_qr_codes(juke_id):
|
|||
"jukebox/jukebox.html",
|
||||
playlists=jukebox.sp_playlists.split(","),
|
||||
juke_id=juke_id,
|
||||
price=jukebox.price
|
||||
price=jukebox.price,
|
||||
inkey=jukebox.inkey
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -89,9 +89,9 @@ async def api_check_credentials_check(sp_id):
|
|||
)
|
||||
async def api_create_update_jukebox(juke_id=None):
|
||||
if juke_id:
|
||||
jukebox = await update_jukebox(juke_id=juke_id, **g.data)
|
||||
jukebox = await update_jukebox(juke_id=juke_id, inkey = g.wallet.inkey, **g.data)
|
||||
else:
|
||||
jukebox = await create_jukebox(**g.data)
|
||||
jukebox = await create_jukebox(inkey = g.wallet.inkey, **g.data)
|
||||
return jsonify(jukebox._asdict()), HTTPStatus.CREATED
|
||||
|
||||
|
||||
|
@ -190,7 +190,7 @@ async def api_get_token(sp_id):
|
|||
return True
|
||||
|
||||
|
||||
######GET INVOICE
|
||||
######GET INVOICE STUFF
|
||||
|
||||
@jukebox_ext.route("/api/v1/jukebox/jb/invoice/<sp_id>/<song_id>", methods=["GET"])
|
||||
async def api_get_jukebox_invoice(sp_id, song_id):
|
||||
|
@ -200,39 +200,76 @@ async def api_get_jukebox_invoice(sp_id, song_id):
|
|||
jukebox_payment = await create_jukebox_payment(song_id,invoice[0])
|
||||
print(jukebox_payment)
|
||||
|
||||
####new table needed to store payment hashes
|
||||
return jsonify(invoice, jukebox_payment)
|
||||
|
||||
|
||||
@jukebox_ext.route("/api/v1/jukebox/jb/invoicecheck/<payment_hash>/<sp_id>", methods=["GET"])
|
||||
async def api_get_jukebox_check_invoice(sp_id, payment_hash):
|
||||
@jukebox_ext.route("/api/v1/jukebox/jb/invoicepaid/<payment_hash>/<sp_id>", methods=["GET"])
|
||||
async def api_get_jukebox_invoice_paid(sp_id, payment_hash):
|
||||
jukebox = await get_jukebox(sp_id)
|
||||
status = await check_invoice_status(jukebox.wallet, payment_hash)
|
||||
is_paid = not status.pending
|
||||
if is_paid:
|
||||
jukebox_payment = await update_jukebox_payment(payment_hash, paid = True)
|
||||
print("https://api.spotify.com/v1/me/player/queue?uri=spotify%3Atrack%3A" + jukebox_payment.song_id + "&device_id=" + jukebox.sp_device)
|
||||
async with httpx.AsyncClient() as client:
|
||||
jukebox_payment = await update_jukebox_payment(payment_hash, paid = True)
|
||||
print("https://api.spotify.com/v1/me/player/queue?uri=spotify%3Atrack%3A" + jukebox_payment.song_id + "&device_id=" + jukebox.sp_device)
|
||||
async with httpx.AsyncClient() as client:
|
||||
try:
|
||||
r = await client.get(
|
||||
"https://api.spotify.com/v1/me/player/queue?uri=spotify%3Atrack%3A" + jukebox_payment.song_id + "&device_id=" + jukebox.sp_device,
|
||||
timeout=40,
|
||||
headers={"Authorization": "Bearer " + jukebox.sp_access_token},
|
||||
)
|
||||
if r.json()["error"]["status"] == 401:
|
||||
token = await api_get_token(sp_id)
|
||||
if token == False:
|
||||
print("invalid")
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
else:
|
||||
return await api_get_jukebox_invoice_paid(sp_id, payment_hash)
|
||||
if r.json()["error"]["status"] == 400:
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
return jsonify(r), HTTPStatus.OK
|
||||
except AssertionError:
|
||||
something = None
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
if not is_paid:
|
||||
return jsonify({"status": False})
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
|
||||
############################GET TRACKS
|
||||
|
||||
@jukebox_ext.route("/api/v1/jukebox/jb/currently/<sp_id>", methods=["GET"])
|
||||
async def api_get_jukebox_currently(sp_id):
|
||||
jukebox = await get_jukebox(sp_id)
|
||||
async with httpx.AsyncClient() as client:
|
||||
try:
|
||||
r = await client.get(
|
||||
"https://api.spotify.com/v1/me/player/currently-playing?market=ES",
|
||||
timeout=40,
|
||||
headers={"Authorization": "Bearer " + jukebox.sp_access_token},
|
||||
)
|
||||
try:
|
||||
if r.json()["item"]:
|
||||
track = {
|
||||
'id': r.json()["item"]["id"],
|
||||
'name': r.json()["item"]["name"],
|
||||
'album': r.json()["item"]["album"]["name"],
|
||||
'artist': r.json()["item"]["artists"][0]["name"],
|
||||
'image': r.json()["item"]["album"]["images"][0]["url"]
|
||||
}
|
||||
return track, HTTPStatus.OK
|
||||
except AssertionError:
|
||||
something = None
|
||||
try:
|
||||
r = await client.get(
|
||||
"https://api.spotify.com/v1/me/player/queue?uri=spotify%3Atrack%3A" + jukebox_payment.song_id + "&device_id=" + jukebox.sp_device,
|
||||
timeout=40,
|
||||
headers={"Authorization": "Bearer " + jukebox.sp_access_token},
|
||||
)
|
||||
if r.json()["error"]["status"] == 401:
|
||||
token = await api_get_token(sp_id)
|
||||
if token == False:
|
||||
print("invalid")
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
else:
|
||||
return await api_get_jukebox_check_invoice(sp_id, payment_hash)
|
||||
if r.json()["error"]["status"] == 400:
|
||||
return await api_get_jukebox_currently(sp_id)
|
||||
elif r.json()["error"]["status"] == 400:
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
|
||||
return r, HTTPStatus.OK
|
||||
except AssertionError:
|
||||
something = None
|
||||
except ValueError:
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
if not is_paid:
|
||||
return jsonify({"status": False})
|
||||
|
||||
except AssertionError:
|
||||
something = None
|
||||
return jsonify({"error": "Something went wrong"})
|
||||
return jsonify({"error": "Something went wrong"})
|
Loading…
Add table
Reference in a new issue