playlists
This commit is contained in:
parent
bd8d0b407e
commit
7e6b65392e
7 changed files with 122 additions and 4 deletions
62
src/library/event.rs
Normal file
62
src/library/event.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use mongod::{
|
||||||
|
assert_reference_of,
|
||||||
|
derive::{Model, Referencable},
|
||||||
|
Model, Referencable, Reference, Validate,
|
||||||
|
};
|
||||||
|
use mongodb::bson::doc;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::library::user::User;
|
||||||
|
|
||||||
|
use super::track::Track;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
|
||||||
|
pub struct Event {
|
||||||
|
pub _id: String,
|
||||||
|
pub kind: EventKind,
|
||||||
|
pub user: Reference,
|
||||||
|
pub track: Reference,
|
||||||
|
pub timestamp: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum EventKind {
|
||||||
|
Play,
|
||||||
|
Played,
|
||||||
|
Stop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub async fn create(kind: EventKind, user: &User, track: Reference) -> Self {
|
||||||
|
let event = Self {
|
||||||
|
_id: uuid::Uuid::new_v4().to_string(),
|
||||||
|
kind: kind,
|
||||||
|
user: user.reference(),
|
||||||
|
track,
|
||||||
|
timestamp: chrono::Utc::now().timestamp(),
|
||||||
|
};
|
||||||
|
|
||||||
|
event.insert().await.unwrap();
|
||||||
|
|
||||||
|
event
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_latest_events_of(u: &User) -> Vec<Self> {
|
||||||
|
Self::find(
|
||||||
|
doc! { "user": u.reference() },
|
||||||
|
Some(300),
|
||||||
|
Some(doc! { "timestamp": -1 }),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Validate for Event {
|
||||||
|
async fn validate(&self) -> Result<(), String> {
|
||||||
|
assert_reference_of!(self.user, User);
|
||||||
|
assert_reference_of!(self.track, Track);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ use crate::cache::RouteCache;
|
||||||
|
|
||||||
pub mod album;
|
pub mod album;
|
||||||
pub mod artist;
|
pub mod artist;
|
||||||
|
pub mod event;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
pub mod playlist;
|
pub mod playlist;
|
||||||
pub mod track;
|
pub mod track;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use mongod::{
|
use mongod::{
|
||||||
assert_reference_of,
|
assert_reference_of,
|
||||||
derive::{Model, Referencable},
|
derive::{Model, Referencable},
|
||||||
|
@ -12,9 +14,9 @@ use crate::{
|
||||||
route::ToAPI,
|
route::ToAPI,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::metadata::AudioMetadata;
|
use super::{event::Event, metadata::AudioMetadata, user::User};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable, PartialEq, Eq)]
|
||||||
pub struct Track {
|
pub struct Track {
|
||||||
pub _id: String,
|
pub _id: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
@ -42,6 +44,22 @@ impl Track {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_latest_of_user(u: &User) -> Vec<Self> {
|
||||||
|
let latest_events = Event::get_latest_events_of(u).await;
|
||||||
|
let mut ids = HashSet::new();
|
||||||
|
let mut tracks = vec![];
|
||||||
|
|
||||||
|
for event in latest_events {
|
||||||
|
let track: Track = event.track.get().await;
|
||||||
|
if !ids.contains(&track._id) {
|
||||||
|
ids.insert(track._id.clone());
|
||||||
|
tracks.push(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracks
|
||||||
|
}
|
||||||
|
|
||||||
/// Transcode audio to OPUS with `bitrate`
|
/// Transcode audio to OPUS with `bitrate`
|
||||||
pub fn get_opus(&self, bitrate: u32) -> Option<String> {
|
pub fn get_opus(&self, bitrate: u32) -> Option<String> {
|
||||||
self.transcode("libopus", bitrate, "opus")
|
self.transcode("libopus", bitrate, "opus")
|
||||||
|
|
|
@ -69,7 +69,8 @@ async fn rocket() -> _ {
|
||||||
route::playlist::playlist_tracks_route,
|
route::playlist::playlist_tracks_route,
|
||||||
route::admin::clean_library,
|
route::admin::clean_library,
|
||||||
route::admin::get_orphans_route,
|
route::admin::get_orphans_route,
|
||||||
route::admin::get_singles_route
|
route::admin::get_singles_route,
|
||||||
|
route::event::event_report_route
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.manage(lib)
|
.manage(lib)
|
||||||
|
|
34
src/route/event.rs
Normal file
34
src/route/event.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use super::api_error;
|
||||||
|
use super::FallibleApiResponse;
|
||||||
|
use mongod::reference_of;
|
||||||
|
use mongod::Model;
|
||||||
|
use mongodb::bson::doc;
|
||||||
|
use rocket::post;
|
||||||
|
use rocket::serde::json::Json;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::library::event::Event;
|
||||||
|
use crate::library::event::EventKind;
|
||||||
|
use crate::library::track::Track;
|
||||||
|
use crate::library::user::User;
|
||||||
|
use mongod::Referencable;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct EventJson {
|
||||||
|
pub kind: EventKind,
|
||||||
|
pub track: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/report", data = "<report>")]
|
||||||
|
pub async fn event_report_route(report: Json<EventJson>, u: User) -> FallibleApiResponse {
|
||||||
|
let track = &report.track;
|
||||||
|
Event::create(
|
||||||
|
report.kind.clone(),
|
||||||
|
&u,
|
||||||
|
reference_of!(Track, track).ok_or_else(|| api_error("Invalid track"))?,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(json!({"ok": 1}))
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ use serde_json::json;
|
||||||
pub mod admin;
|
pub mod admin;
|
||||||
pub mod album;
|
pub mod album;
|
||||||
pub mod artist;
|
pub mod artist;
|
||||||
|
pub mod event;
|
||||||
pub mod playlist;
|
pub mod playlist;
|
||||||
pub mod track;
|
pub mod track;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
|
@ -87,7 +87,8 @@ pub async fn playlist_route(id: &str, u: User) -> FallibleApiResponse {
|
||||||
#[get("/playlist/<id>/tracks")]
|
#[get("/playlist/<id>/tracks")]
|
||||||
pub async fn playlist_tracks_route(id: &str, u: User) -> FallibleApiResponse {
|
pub async fn playlist_tracks_route(id: &str, u: User) -> FallibleApiResponse {
|
||||||
if id == "recents" {
|
if id == "recents" {
|
||||||
// todo : recently played
|
let tracks = Track::get_latest_of_user(&u).await;
|
||||||
|
return Ok(json!(to_api(&tracks).await));
|
||||||
}
|
}
|
||||||
|
|
||||||
if id == "recentlyAdded" {
|
if id == "recentlyAdded" {
|
||||||
|
|
Loading…
Reference in a new issue