- add basic searching query generators to `Artist`, `Collection`, `Track` - add detailed variants of models - split websocket message types to input/output-specific messages to constrain lifetimes - organize imports
173 lines
4.7 KiB
Rust
173 lines
4.7 KiB
Rust
use diesel::prelude::*;
|
|
use diesel::dsl::{AsSelect, Filter, Select, Eq, auto_type};
|
|
use diesel::sqlite::Sqlite;
|
|
use futures::task::waker;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::schema::{artists, collections, tracks};
|
|
use crate::library::Library;
|
|
|
|
type All<S, M> = Select<S, AsSelect<M, Sqlite>>;
|
|
|
|
#[derive(Debug, Clone, Queryable, Selectable, Identifiable)]
|
|
#[diesel(table_name = artists)]
|
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
|
pub struct Artist {
|
|
pub id: i32,
|
|
pub original_name: String,
|
|
pub display_name: String,
|
|
}
|
|
|
|
impl Artist {
|
|
pub fn all() -> All<artists::table, Self> {
|
|
artists::table.select(Self::as_select())
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_id(id: i32) -> _ {
|
|
let all: All<artists::table, Self> = Self::all();
|
|
let filter = artists::id.eq(id);
|
|
all.filter(filter)
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_original_name(name: &str) -> _ {
|
|
let all: All<artists::table, Self> = Self::all();
|
|
let filter = artists::original_name.eq(name);
|
|
all.filter(filter)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Queryable, Selectable, Identifiable)]
|
|
#[diesel(table_name = collections)]
|
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
|
pub struct Collection {
|
|
pub id: i32,
|
|
pub artist_id: Option<i32>,
|
|
pub collection_type: String,
|
|
pub original_name: String,
|
|
pub display_name: String,
|
|
}
|
|
|
|
impl Collection {
|
|
pub fn all() -> All<collections::table, Self> {
|
|
collections::table.select(Self::as_select())
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_id(id: i32) -> _ {
|
|
let all: All<collections::table, Self> = Self::all();
|
|
let filter = collections::id.eq(id);
|
|
all.filter(filter)
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_original_name(name: &str) -> _ {
|
|
let all: All<collections::table, Self> = Self::all();
|
|
let filter = collections::original_name.eq(name);
|
|
all.filter(filter)
|
|
}
|
|
}
|
|
|
|
#[derive(
|
|
Debug, Clone, Queryable, Selectable, Identifiable, Associations, Serialize, Deserialize,
|
|
)]
|
|
#[diesel(table_name = tracks)]
|
|
#[diesel(belongs_to(Artist, foreign_key = artist_id))]
|
|
#[diesel(belongs_to(Collection, foreign_key = collection_id))]
|
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
|
pub struct Track {
|
|
pub id: i32,
|
|
pub file_path: String,
|
|
pub artist_id: Option<i32>,
|
|
pub collection_id: Option<i32>,
|
|
pub original_title: Option<String>,
|
|
pub display_title: Option<String>,
|
|
pub track_number: Option<i32>,
|
|
pub genre: Option<String>,
|
|
pub track_datetime: Option<String>,
|
|
pub length_sec: i32,
|
|
}
|
|
|
|
impl Track {
|
|
pub fn all() -> All<tracks::table, Self> {
|
|
tracks::table.select(Self::as_select())
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_id(id: i32) -> _ {
|
|
let all: All<tracks::table, Self> = Self::all();
|
|
let filter = tracks::id.eq(id);
|
|
all.filter(filter)
|
|
}
|
|
|
|
#[auto_type(no_type_alias)]
|
|
pub fn by_original_title(title: &str) -> _ {
|
|
let all: All<tracks::table, Self> = Self::all();
|
|
let filter = tracks::original_title.eq(title);
|
|
all.filter(filter)
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct DetailedArtist {
|
|
pub id: i32,
|
|
pub original_name: String,
|
|
pub display_name: String,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct DetailedCollection<'a> {
|
|
pub id: i32,
|
|
pub artist: Option<&'a DetailedArtist>,
|
|
pub collection_type: String,
|
|
pub original_name: String,
|
|
pub display_name: String,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct DetailedTrack<'a> {
|
|
pub id: i32,
|
|
pub file_path: String,
|
|
pub artist: Option<&'a DetailedArtist>,
|
|
// a collection could be under another artist (e.g. mixtapes)
|
|
pub collection: Option<&'a DetailedCollection<'a>>,
|
|
pub original_title: Option<String>,
|
|
pub display_title: Option<String>,
|
|
pub track_number: Option<i32>,
|
|
pub genre: Option<String>,
|
|
pub track_datetime: Option<String>,
|
|
pub length_sec: i32,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Insertable)]
|
|
#[diesel(table_name = artists)]
|
|
pub struct NewArtist<'a> {
|
|
pub original_name: &'a str,
|
|
pub display_name: &'a str,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Insertable)]
|
|
#[diesel(table_name = collections)]
|
|
pub struct NewCollection<'a> {
|
|
pub artist_id: Option<i32>,
|
|
pub collection_type: &'a str,
|
|
pub original_name: &'a str,
|
|
pub display_name: &'a str,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Insertable)]
|
|
#[diesel(table_name = tracks)]
|
|
pub struct NewTrack<'a> {
|
|
pub file_path: &'a str,
|
|
pub artist_id: Option<i32>,
|
|
pub collection_id: Option<i32>,
|
|
pub original_title: Option<&'a str>,
|
|
pub display_title: Option<&'a str>,
|
|
pub track_number: Option<i32>,
|
|
pub genre: Option<&'a str>,
|
|
pub track_datetime: Option<&'a str>,
|
|
pub length_sec: i32,
|
|
}
|