daemos 0.1.2

A local-only music player
Documentation
use chrono::{DateTime, Utc};
use color_eyre::Result;
use rusqlite::{Connection, Row, params};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::database::models::utils::parse::{parse_date, parse_uuid};

#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
pub struct PlaylistTrack {
    playlist_id: Uuid,
    track_id: Uuid,
    created_at: DateTime<Utc>,
}

impl TryFrom<&Row<'_>> for PlaylistTrack {
    type Error = rusqlite::Error;

    fn try_from(row: &Row) -> Result<Self, Self::Error> {
        let playlist_id = parse_uuid(row.get("playlist_id")?)?;
        let track_id = parse_uuid(row.get("track_id")?)?;
        let created_at = parse_date(row.get::<_, String>("created_at")?)?;

        let playlist_track = PlaylistTrack {
            playlist_id,
            track_id,
            created_at,
        };

        Ok(playlist_track)
    }
}

impl PlaylistTrack {
    pub fn create(conn: &Connection, playlist_id: Uuid, track_id: Uuid) -> Result<()> {
        let sql = "
            INSERT INTO playlist_tracks (playlist_id, track_id)
            VALUES (?1, ?2)
        ";

        conn.execute(sql, params![playlist_id.to_string(), track_id.to_string()])?;

        Ok(())
    }

    pub fn get(conn: &Connection, playlist_id: Uuid, track_id: Uuid) -> Result<PlaylistTrack> {
        let sql = "
            SELECT playlist_id, track_id, created_at
            FROM playlist_tracks
            WHERE playlist_id = ?1 AND track_id = ?2
        ";

        let mut stmt = conn.prepare(sql)?;

        let track = stmt.query_row(
            params![playlist_id.to_string(), track_id.to_string()],
            |row| PlaylistTrack::try_from(row),
        )?;

        Ok(track)
    }

    pub fn get_all(conn: &Connection) -> Result<Vec<PlaylistTrack>> {
        let sql = "
            SELECT playlist_id, track_id, created_at
            FROM playlist_tracks
        ";

        let mut stmt = conn.prepare(sql)?;

        let tracks = stmt
            .query_map([], |row| PlaylistTrack::try_from(row))?
            .collect::<Result<Vec<_>, _>>()?;

        Ok(tracks)
    }

    pub fn get_by_playlist(conn: &Connection, playlist_id: Uuid) -> Result<Vec<PlaylistTrack>> {
        let sql = "
            SELECT playlist_id, track_id, created_at
            FROM playlist_tracks
            WHERE playlist_id = ?1
        ";

        let mut stmt = conn.prepare(sql)?;

        let tracks = stmt
            .query_map(params![playlist_id.to_string()], |row| {
                PlaylistTrack::try_from(row)
            })?
            .collect::<Result<Vec<_>, _>>()?;

        Ok(tracks)
    }

    pub fn delete(conn: &Connection, playlist_id: Uuid, track_id: Uuid) -> Result<()> {
        let sql = "
            DELETE FROM playlist_tracks
            WHERE playlist_id = ?1 AND track_id = ?2
        ";

        conn.execute(sql, params![playlist_id.to_string(), track_id.to_string()])?;

        Ok(())
    }
}