from yt_dlp import YoutubeDL
from yt_dlp.utils import DownloadError
-DB_VERSION = 2
+DB_VERSION = 3
DATA_DIR = Path(os.environ["DATA_DIR"]) if "DATA_DIR" in os.environ else Path(".")
SCRIPT_DIR = Path(__file__).parent
@app.get("/users/<profile_username>")
def users_profile(profile_username):
- username = session.get("username", None)
# Look up user data for current profile
profile_data = query_db("select * from users where username = ?", [profile_username], one=True)
if profile_data is None:
abort(404)
+ profile_userid = profile_data["userid"]
+
+ # Get playlists for current profile
+ userid = session.get("userid", None)
+ show_private = userid == profile_userid
+ if show_private:
+ plist_data = query_db("select * from playlists where userid = ?", [profile_userid])
+ else:
+ plist_data = query_db("select * from playlists where userid = ? and private = 0", [profile_userid])
# Get songs for current profile
- profile_userid = profile_data["userid"]
songs = Song.get_all_for_userid(profile_userid)
# Sanitize bio
user_fgcolor=profile_data["fgcolor"],
user_bgcolor=profile_data["bgcolor"],
user_accolor=profile_data["accolor"],
+ playlists=plist_data,
+ songs=songs,
song_list=render_template("song-list.html", songs=songs))
@app.post("/edit-profile")
return redirect("/login")
name = request.form["name"]
- if not name:
+ if not name or len(name) > 200:
flash_and_log("Playlist must have a name", "error")
return redirect(request.referrer)
private,
]
)
- flash_and_log(f"Created playlist {plist_data['name']}", "success")
+ get_db().commit()
+ flash_and_log(f"Created playlist {name}", "success")
return redirect(request.referrer)
@app.post("/delete-playlist/<int:playlistid>")
except ValueError:
abort(400)
- plist_data = query_db("select * from playlists where playlistid = ?", args=[playlistid])
+ plist_data = query_db("select * from playlists where playlistid = ?", args=[playlistid], one=True)
if not plist_data:
abort(404)
new_position = len(existing_songs)
# Add to playlist
- query_db("insert into playlist_songs (playlistid, position, songid) values (?, ?, ?)", args=[playlistid, position, songid])
+ query_db("insert into playlist_songs (playlistid, position, songid) values (?, ?, ?)", args=[playlistid, new_position, songid])
# Update modification time
timestamp = datetime.now(timezone.utc).isoformat()
query_db("update playlists set updated = ? where playlistid = ?", args=[timestamp, playlistid])
+ get_db().commit()
return {"status": "ok"}
def playlists(playlistid):
# Make sure playlist exists
- plist_data = query_db("select * from playlists inner join users on playlists.userid = users.userid where playlistid = ?", args=[playlistid])
+ plist_data = query_db("select * from playlists inner join users on playlists.userid = users.userid where playlistid = ?", args=[playlistid], one=True)
if not plist_data:
abort(404)
songs = Song.get_for_playlist(playlistid)
# Show page
- return render_template("playlist.html", name=plist_data["name"], username=plist_data["username"], songs=songs)
+ return render_template(
+ "playlist.html",
+ name=plist_data["name"],
+ username=plist_data["username"],
+ song_list=render_template("song-list.html", songs=songs))
def flash_and_log(msg, category=None):
flash(msg, category)
gifs = "\n".join(gifs)
return gifs
+def get_current_user_playlists():
+ plist_data = []
+ if "userid" in session:
+ plist_data = query_db("select * from playlists where userid = ?", [session["userid"]])
+
+ return plist_data
+
@app.context_processor
def inject_global_vars():
- return dict(gif_data=get_gif_data())
+ return dict(gif_data=get_gif_data(), current_user_playlists=get_current_user_playlists())
################################################################################
def get_for_playlist(cls, playlistid):
return cls._from_db("""\
select * from playlist_songs
- inner join songs on palylist_songs.songid = songs.songid
+ inner join songs on playlist_songs.songid = songs.songid
inner join users on songs.userid = users.userid
order by playlist_songs.position asc
- """, [count])
+ """)
@classmethod
def _from_db(cls, query, args=()):
{% endif %}
+{% if session["userid"] == userid or playlists -%}
+<h2>Playlists</h2>
+{%- endif %}
+
+<!-- Add Playlist button/form -->
+{% if session["userid"] == userid -%}
+<div class="profile-action">
+ <button type="button" class="button" id="add-playlist-button" onclick="showAddPlaylist()">Add Playlist</button>
+ <form action="/create-playlist" method="post" id="create-playlist-form" hidden>
+ <label for="name">Playlist Name</label><br>
+ <input name="name" type="text" maxlength="100" /><br>
+
+ <label for="type">Playlist Type:</label>
+ <input name="type" type="radio" value="private" checked/>
+ <label for="private">Private</label>
+ <input name="type" type="radio" value="public"/>
+ <label for="public">Public</label><br>
+
+ <a href="javascript:hideAddPlaylist();">Cancel</a>
+ <input type="submit" value="Create Playlist" />
+ </form>
+ <script>
+ function showAddPlaylist() {
+ document.getElementById("add-playlist-button").hidden = true;
+ document.getElementById("create-playlist-form").hidden = false;
+ }
+ function hideAddPlaylist() {
+ document.getElementById("add-playlist-button").hidden = false;
+ document.getElementById("create-playlist-form").hidden = true;
+ }
+ </script>
+</div>
+{%- endif %}
+
+{% if playlists -%}
+<div class="playlist-list">
+ {% for plist in playlists -%}
+ <div class="playlist-list-entry">
+ <a class="playlist-name" href="/playlists/{{ plist['playlistid'] }}">{{ plist['name'] }}</a>
+ </div>
+ {%- endfor %}
+</div>
+{%- endif %}
+
+{% if session["userid"] == userid or songs %}
<h2>Songs</h2>
+{% endif %}
<!-- Add Song button -->
{% if session["userid"] == userid %}
</div>
<div class="song-details" {% if request.endpoint != 'song' %}hidden{% endif %}>
- {% if playlists %}
+ {% if current_user_playlists %}
<!-- Add to Playlist Buttons -->
<div class="song-playlist-controls">
- <button type="button" onclick="return showPlaylistSelector(event, {{ song.songid }})">Add to Playlist</button>
+ <button type="button" class="button" onclick="return showPlaylistSelector(event, {{ song.songid }})">Add to Playlist</button>
</div>
{% endif %}
</div>
{% endfor %}
- {% if playlists -%}
+ {% if current_user_playlists -%}
<!-- Playlist selector, shown when Add to Playlist is clicked -->
<div class="playlist-selector" hidden>
- <form>
+ <form action="/append-to-playlist" method="post">
<input type="hidden" name="songid" value="-1" id="playlist-selector-songid"/>
<select name="playlistid">
- {% for plist in playlists -%}
- <option value="{{ plist.playlistid }}">{{ plist.name }}</option>
+ {% for plist in current_user_playlists -%}
+ <option value="{{ plist.playlistid }}">{{ plist['name'] }}</option>
{%- endfor %}
</select>
<input type="submit" value="submit" />
return false;
}
-{% if playlists %}
+{% if current_user_playlists %}
var m_addToPlaylistSongid = null;
function showPlaylistSelector(event, songid) {
m_addToPlaylistSongid = songid;
var playlistSelector = songList.querySelector(".playlist-selector");
playlistSelector.hidden = false;
var songidInput = playlistSelector.querySelector("#playlist-selector-songid")
- songInput.value = songid
+ songidInput.value = songid
return false;
}
-{% endif $}
+{% endif %}
</script>