Compare commits

..

No commits in common. "0ee634c515618e9340bbb317c4a4efcb41325f00" and "9d5373797c32665da3927c6dfdf03fc379e01774" have entirely different histories.

23 changed files with 485 additions and 1021 deletions

View file

@ -1,9 +1,4 @@
{ {
"sqltools.useNodeRuntime": true, "sqltools.useNodeRuntime": true,
"sqltools.connections": [], "sqltools.connections": []
"cSpell.words": [
"appender",
"audiotags",
"powi"
]
} }

View file

@ -7,6 +7,7 @@ steps:
settings: settings:
platform: linux/amd64 platform: linux/amd64
repo: forge.lys.ee/lyssieth/rave repo: forge.lys.ee/lyssieth/rave
secrets: [forge_username, forge_password]
dockerfile: Dockerfile dockerfile: Dockerfile
tags: tags:
- latest - latest

1391
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
pub mod prelude; pub mod prelude;

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
pub use super::album::Entity as Album; pub use super::album::Entity as Album;
pub use super::artist::Entity as Artist; pub use super::artist::Entity as Artist;

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -61,7 +61,6 @@ impl MigrationTrait for Migration {
} }
} }
#[allow(clippy::enum_variant_names)]
#[derive(DeriveIden)] #[derive(DeriveIden)]
pub enum Artist { pub enum Artist {
Table, Table,

View file

@ -121,7 +121,6 @@ impl MigrationTrait for Migration {
} }
} }
#[allow(clippy::enum_variant_names)]
#[derive(DeriveIden)] #[derive(DeriveIden)]
pub enum Track { pub enum Track {
Table, Table,

View file

@ -8,16 +8,16 @@ default-run = "rave"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
cfg-if = "1.0" cfg-if = "1.0.0"
color-eyre = "0.6" color-eyre = "0.6"
md5 = "0.7" md5 = "0.7"
poem = { version = "2.0", features = [ poem = { version = "1.3", features = [
"compression", "compression",
"cookie", "cookie",
"session", "session",
"static-files", "static-files",
"xml", "xml",
"tower-compat", "tower-compat",
] } ] }
quick-xml = { version = "0.31", features = ["serialize"] } quick-xml = { version = "0.31", features = ["serialize"] }
serde = { workspace = true } serde = { workspace = true }
@ -26,11 +26,11 @@ time = { workspace = true, features = ["local-offset"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tracing = { workspace = true } tracing = { workspace = true }
tracing-subscriber = { version = "0.3", features = [ tracing-subscriber = { version = "0.3", features = [
"env-filter", "env-filter",
"tracing", "tracing",
"parking_lot", "parking_lot",
"time", "time",
"json", "json",
] } ] }
url = { version = "2.5", features = ["serde"] } url = { version = "2.5", features = ["serde"] }
url-escape = "0.1" url-escape = "0.1"
@ -39,10 +39,10 @@ entities = { workspace = true }
migration = { workspace = true } migration = { workspace = true }
once_cell = { version = "1", features = ["parking_lot"] } once_cell = { version = "1", features = ["parking_lot"] }
futures = "0.3" futures = "0.3"
audiotags = "0.5" audiotags = "0.4"
tracing-appender = "0.2" tracing-appender = "0.2"
blake3 = "1.5" blake3 = "1.5"
image = "0.25" image = "0.24"
nate = "0.4" nate = "0.4"
rand = "0.8" rand = "0.8"
http-range = "0.1" http-range = "0.1"

View file

@ -8,7 +8,13 @@
use color_eyre::Result; use color_eyre::Result;
use migration::{Migrator, MigratorTrait}; use migration::{Migrator, MigratorTrait};
use poem::{http::StatusCode, listener::TcpListener, middleware, Endpoint, EndpointExt, Route}; use poem::{
http::StatusCode,
listener::TcpListener,
middleware,
web::{CompressionAlgo, CompressionLevel},
Endpoint, EndpointExt, Route,
};
use sea_orm::{ConnectOptions, Database, DatabaseConnection}; use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use tracing::info; use tracing::info;
use tracing_appender::non_blocking::WorkerGuard; use tracing_appender::non_blocking::WorkerGuard;
@ -68,6 +74,11 @@ fn create_route() -> Box<dyn Endpoint<Output = poem::Response>> {
.nest("/", ui::build()) .nest("/", ui::build())
.nest("/rest", rest::build()) .nest("/rest", rest::build())
.with(middleware::CatchPanic::new()) .with(middleware::CatchPanic::new())
.with(
middleware::Compression::new()
.algorithms([CompressionAlgo::BR, CompressionAlgo::GZIP])
.with_quality(CompressionLevel::Default),
)
.with(middleware::Tracing) .with(middleware::Tracing)
.with(middleware::CookieJarManager::new()) .with(middleware::CookieJarManager::new())
.with(middleware::NormalizePath::new( .with(middleware::NormalizePath::new(

View file

@ -143,7 +143,6 @@ async fn album_to_album_id3(conn: DbTxn, album: &album::Model) -> Result<AlbumId
Ok(AlbumId3::new(album.clone(), artist, genre)) Ok(AlbumId3::new(album.clone(), artist, genre))
} }
#[allow(clippy::no_effect_underscore_binding)]
#[instrument(skip(_conn, _params))] #[instrument(skip(_conn, _params))]
async fn get_album_list_random( async fn get_album_list_random(
_conn: DbTxn, _conn: DbTxn,

View file

@ -2,7 +2,6 @@ use std::{io::Cursor, path::PathBuf};
use crate::{json_or_xml, utils::db::DbTxn}; use crate::{json_or_xml, utils::db::DbTxn};
use entities::prelude::CoverArt; use entities::prelude::CoverArt;
use image::ImageFormat;
use poem::{ use poem::{
http::StatusCode, http::StatusCode,
web::{Data, Query}, web::{Data, Query},
@ -135,9 +134,9 @@ pub async fn get_cover_art(
let res = resize.write_to( let res = resize.write_to(
&mut buf, &mut buf,
match ext { match ext {
"jpg" => ImageFormat::Jpeg, "jpg" => image::ImageOutputFormat::Jpeg(100),
"png" => ImageFormat::Png, "png" => image::ImageOutputFormat::Png,
"gif" => ImageFormat::Gif, "gif" => image::ImageOutputFormat::Gif,
_ => { _ => {
return json_or_xml!(auth, SubsonicResponse::new_error(Error::Generic(None))); return json_or_xml!(auth, SubsonicResponse::new_error(Error::Generic(None)));
} }

View file

@ -62,8 +62,13 @@ pub async fn handle(
am.suffix = Set("flac".to_string()); am.suffix = Set("flac".to_string());
am.path = Set(path.to_string_lossy().to_string()); am.path = Set(path.to_string_lossy().to_string());
am.is_dir = Set(false); am.is_dir = Set(false);
am.track_number = Set(tag.track_number().map(i32::from)); am.track_number = Set(tag
if let Some(disc_number) = tag.disc_number().map(i32::from) { .track_number()
.map(|v| i32::try_from(v).expect("failed to convert track to i32")));
if let Some(disc_number) = tag
.disc_number()
.map(|v| i32::try_from(v).expect("failed to convert disc to i32"))
{
am.disc_number = Set(disc_number); am.disc_number = Set(disc_number);
} }
am.is_video = Set(false); am.is_video = Set(false);
@ -160,7 +165,10 @@ async fn find_album(
am.genre_ids = Set(Some(vec![genre_id])); am.genre_ids = Set(Some(vec![genre_id]));
} }
} }
am.song_count = Set(tag.total_tracks().map(i64::from).unwrap_or_default()); am.song_count = Set(tag
.total_tracks()
.map(|v| i64::try_from(v).expect("Failed to convert total tracks to i32"))
.unwrap_or_default());
am.duration = Set(tag am.duration = Set(tag
.duration() .duration()
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly .map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly

View file

@ -62,8 +62,13 @@ pub async fn handle(
am.suffix = Set("mp3".to_string()); am.suffix = Set("mp3".to_string());
am.path = Set(path.to_string_lossy().to_string()); am.path = Set(path.to_string_lossy().to_string());
am.is_dir = Set(false); am.is_dir = Set(false);
am.track_number = Set(tag.track_number().map(i32::from)); am.track_number = Set(tag
if let Some(disc_number) = tag.disc_number().map(i32::from) { .track_number()
.map(|v| i32::try_from(v).expect("failed to convert track to i32")));
if let Some(disc_number) = tag
.disc_number()
.map(|v| i32::try_from(v).expect("failed to convert disc to i32"))
{
am.disc_number = Set(disc_number); am.disc_number = Set(disc_number);
} }
am.is_video = Set(false); am.is_video = Set(false);
@ -160,7 +165,10 @@ async fn find_album(
am.genre_ids = Set(Some(vec![genre_id])); am.genre_ids = Set(Some(vec![genre_id]));
} }
} }
am.song_count = Set(tag.total_tracks().map(i64::from).unwrap_or_default()); am.song_count = Set(tag
.total_tracks()
.map(|v| i64::try_from(v).expect("Failed to convert total tracks to i32"))
.unwrap_or_default());
am.duration = Set(tag am.duration = Set(tag
.duration() .duration()
.map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly .map(|c| c.round().rem_euclid(2f64.powi(32)) as i64) // TODO: figure out how to do this properly

View file

@ -2,7 +2,6 @@ use entities::artist;
use serde::Serialize; use serde::Serialize;
use time::format_description::well_known::Iso8601; use time::format_description::well_known::Iso8601;
#[allow(clippy::struct_field_names)]
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct Artist { pub struct Artist {
#[serde(rename = "id")] #[serde(rename = "id")]

View file

@ -4,7 +4,6 @@ use time::format_description::well_known::Iso8601;
use crate::subsonic::{Album, Artist}; use crate::subsonic::{Album, Artist};
#[allow(clippy::struct_field_names)]
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct Child { pub struct Child {
#[serde(rename = "id")] #[serde(rename = "id")]