Add playlist export and SEO meta tags

Add text/CSV export endpoints for playlists and saved recommendations.
Add export buttons to PlaylistDetail and Recommendations pages.
Add Open Graph and Twitter meta tags to index.html for better SEO.
This commit is contained in:
root
2026-03-31 20:49:07 -05:00
parent 957a66bbd0
commit 5215e8c792
6 changed files with 138 additions and 6 deletions

View File

@@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import PlainTextResponse
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
@@ -49,6 +50,39 @@ async def get_playlist(
return playlist
@router.get("/{playlist_id}/export")
async def export_playlist(
playlist_id: int,
format: str = Query("text", pattern="^(text|csv)$"),
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
result = await db.execute(
select(Playlist).options(selectinload(Playlist.tracks))
.where(Playlist.id == playlist_id, Playlist.user_id == user.id)
)
playlist = result.scalar_one_or_none()
if not playlist:
raise HTTPException(status_code=404, detail="Playlist not found")
if format == "csv":
lines = ["Title,Artist,Album"]
for t in playlist.tracks:
# Escape commas in CSV
title = f'"{t.title}"' if ',' in t.title else t.title
artist = f'"{t.artist}"' if ',' in t.artist else t.artist
album = f'"{t.album}"' if t.album and ',' in t.album else (t.album or '')
lines.append(f"{title},{artist},{album}")
return PlainTextResponse("\n".join(lines), media_type="text/csv",
headers={"Content-Disposition": f'attachment; filename="{playlist.name}.csv"'})
else:
lines = [f"{playlist.name}", "=" * len(playlist.name), ""]
for i, t in enumerate(playlist.tracks, 1):
lines.append(f"{i}. {t.artist} - {t.title}")
return PlainTextResponse("\n".join(lines), media_type="text/plain",
headers={"Content-Disposition": f'attachment; filename="{playlist.name}.txt"'})
@router.delete("/{playlist_id}")
async def delete_playlist(
playlist_id: int,