replace playlist delete page with playlist manage page
This commit is contained in:
parent
b633abdb6e
commit
b136285c00
@ -64,7 +64,7 @@ class Db:
|
|||||||
self.rdb.set(Key.playlist_count(playlist_id), count)
|
self.rdb.set(Key.playlist_count(playlist_id), count)
|
||||||
self.rdb.set(Key.playlist_counttype(playlist_id), counttype)
|
self.rdb.set(Key.playlist_counttype(playlist_id), counttype)
|
||||||
|
|
||||||
def user_del_playlist(self, spotify_id, playlist_id):
|
def user_del_playlist(self, spotify_id, playlist_id, delete_on_spotify = True):
|
||||||
self.rdb.srem(Key.user_playlists(spotify_id), playlist_id)
|
self.rdb.srem(Key.user_playlists(spotify_id), playlist_id)
|
||||||
self.rdb.delete(Key.playlist_count(playlist_id))
|
self.rdb.delete(Key.playlist_count(playlist_id))
|
||||||
self.rdb.delete(Key.playlist_counttype(playlist_id))
|
self.rdb.delete(Key.playlist_counttype(playlist_id))
|
||||||
|
@ -10,6 +10,7 @@ Jinja2==3.1.2
|
|||||||
MarkupSafe==2.1.1
|
MarkupSafe==2.1.1
|
||||||
redis==4.4.0
|
redis==4.4.0
|
||||||
requests==2.28.1
|
requests==2.28.1
|
||||||
|
requests-futures==1.0.0
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
urllib3==1.26.13
|
urllib3==1.26.13
|
||||||
Werkzeug==2.2.2
|
Werkzeug==2.2.2
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from flask import Flask, render_template, request, make_response, redirect, url_for
|
from flask import Flask, render_template, request, make_response, redirect, url_for
|
||||||
import requests as rq
|
import requests as rq
|
||||||
|
from requests_futures.sessions import FuturesSession
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import base64
|
import base64
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
@ -51,6 +52,9 @@ def isauth(cookies):
|
|||||||
|
|
||||||
return user_secret == db.get_user_client_secret(user_id)
|
return user_secret == db.get_user_client_secret(user_id)
|
||||||
|
|
||||||
|
def create_empty_message():
|
||||||
|
return { 'type':'', 'text': u'\u00A0'}
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", methods=['GET', 'POST'])
|
@app.route("/", methods=['GET', 'POST'])
|
||||||
def index():
|
def index():
|
||||||
@ -67,7 +71,7 @@ def index():
|
|||||||
'redirect_uri': BASE_URL + url_for('cb'),
|
'redirect_uri': BASE_URL + url_for('cb'),
|
||||||
'response_type': 'code'
|
'response_type': 'code'
|
||||||
}),
|
}),
|
||||||
message = { 'type':'', 'text': ''}
|
message = create_empty_message()
|
||||||
))
|
))
|
||||||
resp.set_cookie(
|
resp.set_cookie(
|
||||||
'user_secret',
|
'user_secret',
|
||||||
@ -81,7 +85,7 @@ def index():
|
|||||||
|
|
||||||
if request.method=='GET':
|
if request.method=='GET':
|
||||||
message = request.args.get('message')
|
message = request.args.get('message')
|
||||||
return render_template("index_authorised.html", message = json.loads(message) if message else "" )
|
return render_template("index_authorised.html", message = json.loads(message) if message else create_empty_message())
|
||||||
|
|
||||||
|
|
||||||
playlist_name = request.form.get('pname')
|
playlist_name = request.form.get('pname')
|
||||||
@ -180,20 +184,73 @@ def logout():
|
|||||||
resp.set_cookie('user_secret', '')
|
resp.set_cookie('user_secret', '')
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/delete')
|
@app.route('/manage')
|
||||||
def delete():
|
def manage():
|
||||||
if not isauth(request.cookies):
|
if not isauth(request.cookies):
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
user_id = request.cookies.get('spotify_id')
|
user_id = request.cookies.get('spotify_id')
|
||||||
playlist_id = request.args.get('playlist')
|
playlist_id = request.args.get('playlist_id')
|
||||||
|
action = request.args.get('action')
|
||||||
|
|
||||||
|
def gen_populated_response(message = False):
|
||||||
|
session = FuturesSession()
|
||||||
|
futures = []
|
||||||
|
ids = db.get_user_playlists(user_id)
|
||||||
|
playlists = []
|
||||||
|
headers = { 'Authorization': f'Bearer {db.get_user_auth_token(user_id)}' }
|
||||||
|
for pl_id in ids:
|
||||||
|
futures.append(session.get(f"{SPOTIFY_API_ENDPOINT}/playlists/{pl_id}?fields=id,name", headers = headers))
|
||||||
|
|
||||||
|
for future in futures:
|
||||||
|
resp = future.result()
|
||||||
|
if resp.status_code != 200:
|
||||||
|
# fail silently for now...
|
||||||
|
# TODO maybe report this error l8r to user, log
|
||||||
|
print(f"NONZERO STATUS CODE: {resp.status_code=}")
|
||||||
|
print(f"{resp.content=}")
|
||||||
|
continue
|
||||||
|
resp = resp.json()
|
||||||
|
playlists.append(resp)
|
||||||
|
|
||||||
|
if not message:
|
||||||
|
message = create_empty_message()
|
||||||
|
if len(ids) == 0:
|
||||||
|
message['type'] = 'info'
|
||||||
|
message['text'] = 'no playlists managed by heartbeats'
|
||||||
|
message_str = request.args.get('message')
|
||||||
|
if message_str:
|
||||||
|
message = json.loads(message_str)
|
||||||
|
|
||||||
|
return render_template("manage.html", message=message, playlists=playlists)
|
||||||
|
|
||||||
if not playlist_id:
|
if not playlist_id:
|
||||||
return render_template("delete.html", message={'type':'', 'text': ''}, playlist_ids=db.get_user_playlists(user_id))
|
return gen_populated_response()
|
||||||
|
|
||||||
db.user_del_playlist(user_id, playlist_id)
|
if action in [ 'delete', 'unlink' ]:
|
||||||
|
actioned = 'deleted' if action == 'delete' else 'unlinked'
|
||||||
|
if action == 'delete':
|
||||||
|
headers = { 'Authorization': f'Bearer {db.get_user_auth_token(user_id)}' }
|
||||||
|
resp = rq.delete(
|
||||||
|
f"{SPOTIFY_API_ENDPOINT}/playlists/{playlist_id}/followers",
|
||||||
|
headers = headers
|
||||||
|
)
|
||||||
|
print(resp.content)
|
||||||
|
if resp.status_code != 200:
|
||||||
|
return redirect(url_for('manage', message=json.dumps({
|
||||||
|
'type': 'error',
|
||||||
|
'text': f'unable to {action} playlist {playlist_name}'
|
||||||
|
})))
|
||||||
|
|
||||||
return render_template("delete.html", message={
|
|
||||||
'type': 'info',
|
db.user_del_playlist(user_id, playlist_id)
|
||||||
'text': f'successfully deleted playlist {playlist_id=}'
|
playlist_name = request.args.get('playlist_name')
|
||||||
}, playlist_ids=db.get_user_playlists(user_id))
|
return redirect(url_for('manage', message=json.dumps({
|
||||||
|
'type': 'info',
|
||||||
|
'text': f'successfully {actioned} playlist {playlist_name}'
|
||||||
|
})))
|
||||||
|
|
||||||
|
return gen_populated_response(message={
|
||||||
|
'type': 'error',
|
||||||
|
'text': f'action not recognised: {action}'
|
||||||
|
})
|
||||||
|
@ -28,6 +28,7 @@ a, a:visited {
|
|||||||
#message { padding: 1em; }
|
#message { padding: 1em; }
|
||||||
</style>
|
</style>
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}{% endblock %}</title>
|
||||||
|
{% block extrahead %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p class="messagetype{{message['type']}}"id="message">{{message['text']}}</p>
|
<p class="messagetype{{message['type']}}"id="message">{{message['text']}}</p>
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block title %}heartbeats | delete a playlist{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1> delete a playlist </h1>
|
|
||||||
<ul>
|
|
||||||
{% for pid in playlist_ids %}
|
|
||||||
<li><a href="?playlist={{pid}}">{{pid}}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="..">home</a>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -22,5 +22,5 @@
|
|||||||
<br>
|
<br>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p><a href="./delete">delete a playlist</a>, <a href="./logout">logout</a></p>
|
<p><a href="./manage">manage playlists</a>, <a href="./logout">logout</a></p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
56
web/src/templates/manage.html
Normal file
56
web/src/templates/manage.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}heartbeats | manage playlists{% endblock %}
|
||||||
|
|
||||||
|
{% block extrahead %}
|
||||||
|
<style>
|
||||||
|
.playlists * {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-content: last baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .name {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .actions a { padding: 0; }
|
||||||
|
.playlist .actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist:nth-child(even) {
|
||||||
|
background-color: var(--bg-lc);
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlists .actions a { padding: 0; }
|
||||||
|
|
||||||
|
span {
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<h1><span style="color: #1db954">manage</span> playlists</h1>
|
||||||
|
<div class="playlists">
|
||||||
|
{% for playlist in playlists %}
|
||||||
|
<div class="playlist">
|
||||||
|
<span class="name" title="{{playlist['name']}} ({{playlist['id']}})">{{playlist['name']}}</span>
|
||||||
|
<div class="actions">
|
||||||
|
<a href="?playlist_id={{playlist['id']}}&playlist_name={{playlist['name']}}&action=delete">delete</a>
|
||||||
|
<a href="?playlist_id={{playlist['id']}}&playlist_name={{playlist['name']}}&action=unlink">unlink without deleting</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--a href="..">home</a-->
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user