from typing import List from sqlalchemy.orm import Session from sqlalchemy import func, desc from app.models.song import Song, song_playlist from app.models.playlist import Playlist from app.models.artist import Artist def get_similar_songs(db: Session, song_id: int, limit: int = 10) -> List[Song]: """ Get similar songs based on the same artist and album. """ # Get the current song current_song = db.query(Song).filter(Song.id == song_id).first() if not current_song: return [] # Find songs from the same artist and album (if applicable) query = db.query(Song).filter(Song.id != song_id) if current_song.album_id: # Prioritize songs from same album query = query.filter(Song.album_id == current_song.album_id) else: # Otherwise, find songs from the same artist query = query.filter(Song.artist_id == current_song.artist_id) return query.limit(limit).all() def get_recommended_songs_for_user(db: Session, user_id: int, limit: int = 10) -> List[Song]: """ Get song recommendations for a user based on their playlists. """ # First get all songs in user's playlists user_playlist_songs = ( db.query(Song.id) .join(song_playlist) .join(Playlist) .filter(Playlist.user_id == user_id) .subquery() ) # Get artists that the user listens to user_artists = ( db.query(Artist.id) .join(Song, Song.artist_id == Artist.id) .join(user_playlist_songs, user_playlist_songs.c.id == Song.id) .distinct() .subquery() ) # Recommend songs from the same artists that aren't in the user's playlists recommended = ( db.query(Song) .join(Artist, Song.artist_id == Artist.id) .filter( Song.id.notin_(user_playlist_songs), Artist.id.in_(user_artists) ) .order_by(func.random()) .limit(limit) .all() ) return recommended def get_popular_songs(db: Session, limit: int = 10) -> List[Song]: """ Get popular songs based on how many playlists they appear in. """ # Count the number of playlists each song is in song_counts = ( db.query( Song, func.count(song_playlist.c.playlist_id).label("playlist_count") ) .join(song_playlist) .group_by(Song.id) .order_by(desc("playlist_count")) .limit(limit) .all() ) # Extract just the songs return [song for song, _ in song_counts] def get_artist_recommendations(db: Session, artist_id: int, limit: int = 5) -> List[Artist]: """ Get similar artists based on the given artist. """ # This is a very simple implementation that just returns random artists # In a real system, this would use more sophisticated algorithms return ( db.query(Artist) .filter(Artist.id != artist_id) .order_by(func.random()) .limit(limit) .all() )