playlists

This commit is contained in:
JMARyA 2024-08-17 01:25:41 +02:00
parent bd8d0b407e
commit 7e6b65392e
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
7 changed files with 122 additions and 4 deletions

62
src/library/event.rs Normal file
View 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(())
}
}

View file

@ -12,6 +12,7 @@ use crate::cache::RouteCache;
pub mod album;
pub mod artist;
pub mod event;
pub mod metadata;
pub mod playlist;
pub mod track;

View file

@ -1,3 +1,5 @@
use std::collections::HashSet;
use mongod::{
assert_reference_of,
derive::{Model, Referencable},
@ -12,9 +14,9 @@ use crate::{
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 _id: String,
pub path: String,
@ -42,6 +44,22 @@ impl Track {
.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`
pub fn get_opus(&self, bitrate: u32) -> Option<String> {
self.transcode("libopus", bitrate, "opus")

View file

@ -69,7 +69,8 @@ async fn rocket() -> _ {
route::playlist::playlist_tracks_route,
route::admin::clean_library,
route::admin::get_orphans_route,
route::admin::get_singles_route
route::admin::get_singles_route,
route::event::event_report_route
],
)
.manage(lib)

34
src/route/event.rs Normal file
View 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}))
}

View file

@ -8,6 +8,7 @@ use serde_json::json;
pub mod admin;
pub mod album;
pub mod artist;
pub mod event;
pub mod playlist;
pub mod track;
pub mod user;

View file

@ -87,7 +87,8 @@ pub async fn playlist_route(id: &str, u: User) -> FallibleApiResponse {
#[get("/playlist/<id>/tracks")]
pub async fn playlist_tracks_route(id: &str, u: User) -> FallibleApiResponse {
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" {