Merge 5ca38939bd into release

This commit is contained in:
github-actions[bot] 2024-02-03 04:27:44 +00:00 committed by GitHub
commit bb11c80ebd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 700 additions and 435 deletions

View file

@ -1,6 +1,9 @@
coverage:
range: "0...100"
status:
patch:
default:
informational: true
project:
default:
informational: true

View file

@ -1,5 +1,17 @@
# Changelog
## Polaris 0.14.1
### Server
- Fixed compilation issue when using musl toolchains
- Log messages that DDNS is not setup have been downgraded to debug level
### Web client
- Fixed a bug where non-ASCII files or directories were not always alphabetically sorted (thanks @dechamps)
- Fixed a bug where after linking a last.fm account, clicking the account name would not link to the expected page
## Polaris 0.14.0
### General

1038
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -14,17 +14,20 @@ ui = ["native-windows-gui", "native-windows-derive"]
actix-files = { version = "0.6" }
actix-web = { version = "4" }
actix-web-httpauth = { version = "0.8" }
ape = "0.4.0"
base64 = "0.13"
ape = "0.5"
base64 = "0.21"
branca = "0.10.1"
crossbeam-channel = "0.5"
diesel_migrations = { version = "2.0", features = ["sqlite"] }
futures-util = { version = "0.3" }
getopts = "0.2.21"
http = "0.2.8"
id3 = { git = "https://github.com/polyfloyd/rust-id3.git", rev = "f3b5e3a" } # TODO update after 1.5.0 is released
id3 = "1.7.0"
lewton = "0.10.2"
libsqlite3-sys = { version = "0.25", features = ["bundled", "bundled-windows"], optional = true }
libsqlite3-sys = { version = "0.26", features = [
"bundled",
"bundled-windows",
], optional = true }
log = "0.4.17"
metaflac = "0.2.5"
mp3-duration = "0.1.10"
@ -42,9 +45,8 @@ serde_derive = "1.0.147"
serde_json = "1.0.87"
simplelog = "0.12.0"
thiserror = "1.0.37"
tokio = "1.21"
toml = "0.5"
ureq = "1.5.5"
toml = "0.7"
ureq = "2.7"
url = "2.3"
[dependencies.diesel]
@ -58,11 +60,17 @@ default_features = false
features = ["bmp", "gif", "jpeg", "png"]
[target.'cfg(windows)'.dependencies]
native-windows-gui = {version = "1.0.13", default-features = false, features = ["cursor", "image-decoder", "message-window", "menu", "tray-notification"], optional = true }
native-windows-derive = {version = "1.0.5", optional = true }
native-windows-gui = { version = "1.0.13", default-features = false, features = [
"cursor",
"image-decoder",
"message-window",
"menu",
"tray-notification",
], optional = true }
native-windows-derive = { version = "1.0.5", optional = true }
[target.'cfg(unix)'.dependencies]
daemonize = "0.4.1"
daemonize = "0.5"
sd-notify = "0.4.1"
[target.'cfg(windows)'.build-dependencies]

View file

@ -21,7 +21,9 @@ Password: `demo_password`
- Support for `flac`, `mp3`, `mp4`, `mpc`, `ogg`, `opus`, `ape`, `wav` and `aiff` files
- Easy to setup and administer, no configuration files needed
- Dark mode and customizable color themes
- Listen to your music on the go with [Polaris Android](https://github.com/agersant/polaris-android)
- Listen to your music on the go:
- Polaris Android ([Google Play Store](https://play.google.com/store/apps/details?id=agersant.polaris) · [F-Droid](https://f-droid.org/packages/agersant.polaris/) · [Repository](https://github.com/agersant/polaris-android))
- Polarios ([App Store](https://apps.apple.com/app/polarios/id1662366309) · [Repository](https://gitlab.com/elise/Polarios))
- [Last.fm](https://www.last.fm) scrobbling
## Tutorials

Binary file not shown.

View file

@ -1,5 +1,6 @@
use base64::prelude::*;
use diesel::prelude::*;
use log::{error, info};
use log::{debug, error};
use serde::{Deserialize, Serialize};
use std::thread;
use std::time;
@ -12,6 +13,8 @@ const DDNS_UPDATE_URL: &str = "https://ydns.io/api/v1/update/";
pub enum Error {
#[error("DDNS update query failed with HTTP status code `{0}`")]
UpdateQueryFailed(u16),
#[error("DDNS update query failed due to a transport error")]
UpdateQueryTransport,
#[error(transparent)]
DatabaseConnection(#[from] db::Error),
#[error(transparent)]
@ -39,19 +42,23 @@ impl Manager {
fn update_my_ip(&self) -> Result<(), Error> {
let config = self.config()?;
if config.host.is_empty() || config.username.is_empty() {
info!("Skipping DDNS update because credentials are missing");
debug!("Skipping DDNS update because credentials are missing");
return Ok(());
}
let full_url = format!("{}?host={}", DDNS_UPDATE_URL, &config.host);
let credentials = format!("{}:{}", &config.username, &config.password);
let response = ureq::get(full_url.as_str())
.auth(&config.username, &config.password)
.set(
"Authorization",
&format!("Basic {}", BASE64_STANDARD_NO_PAD.encode(credentials)),
)
.call();
if response.ok() {
Ok(())
} else {
Err(Error::UpdateQueryFailed(response.status()))
match response {
Ok(_) => Ok(()),
Err(ureq::Error::Status(code, _)) => Err(Error::UpdateQueryFailed(code)),
Err(ureq::Error::Transport(_)) => Err(Error::UpdateQueryTransport),
}
}

View file

@ -56,7 +56,6 @@ impl From<id3::Tag> for SongTags {
let track_number = tag.track();
let year = tag
.year()
.map(|y| y as i32)
.or_else(|| tag.date_released().map(|d| d.year))
.or_else(|| tag.original_date_released().map(|d| d.year))
.or_else(|| tag.date_recorded().map(|d| d.year));
@ -316,9 +315,7 @@ fn read_flac(path: &Path) -> Result<SongTags, Error> {
let year = vorbis.get("DATE").and_then(|d| d[0].parse::<i32>().ok());
let mut streaminfo = tag.get_blocks(metaflac::BlockType::StreamInfo);
let duration = match streaminfo.next() {
Some(&metaflac::Block::StreamInfo(ref s)) => {
Some((s.total_samples as u32 / s.sample_rate) as u32)
}
Some(metaflac::Block::StreamInfo(s)) => Some(s.total_samples as u32 / s.sample_rate),
_ => None,
};
let has_artwork = tag.pictures().count() > 0;

View file

@ -34,7 +34,7 @@ fn update_removes_missing_content() {
let copy_options = fs_extra::dir::CopyOptions::new();
fs_extra::dir::copy(
&original_collection_dir,
original_collection_dir,
&builder.test_directory,
&copy_options,
)
@ -55,7 +55,7 @@ fn update_removes_missing_content() {
}
let khemmis_directory = test_collection_dir.join("Khemmis");
std::fs::remove_dir_all(&khemmis_directory).unwrap();
std::fs::remove_dir_all(khemmis_directory).unwrap();
ctx.index.update().unwrap();
{
let mut connection = ctx.db.connect().unwrap();
@ -124,7 +124,7 @@ fn can_flatten_directory() {
.build();
ctx.index.update().unwrap();
let path: PathBuf = [TEST_MOUNT_NAME, "Tobokegao"].iter().collect();
let songs = ctx.index.flatten(&path).unwrap();
let songs = ctx.index.flatten(path).unwrap();
assert_eq!(songs.len(), 8);
}
@ -135,7 +135,7 @@ fn can_flatten_directory_with_shared_prefix() {
.build();
ctx.index.update().unwrap();
let path: PathBuf = [TEST_MOUNT_NAME, "Tobokegao", "Picnic"].iter().collect(); // Prefix of '(Picnic Remixes)'
let songs = ctx.index.flatten(&path).unwrap();
let songs = ctx.index.flatten(path).unwrap();
assert_eq!(songs.len(), 7);
}

View file

@ -99,7 +99,7 @@ impl Manager {
if let Some(sleep_duration) = new_settings.reindex_every_n_seconds {
diesel::update(misc_settings::table)
.set(misc_settings::index_sleep_duration_seconds.eq(sleep_duration as i32))
.set(misc_settings::index_sleep_duration_seconds.eq(sleep_duration))
.execute(&mut connection)?;
}

View file

@ -26,7 +26,7 @@ pub struct ContextBuilder {
impl ContextBuilder {
pub fn new(test_name: String) -> Self {
Self {
test_directory: prepare_test_directory(&test_name),
test_directory: prepare_test_directory(test_name),
config: config::Config::default(),
}
}

View file

@ -31,7 +31,7 @@ pub enum Error {
CliArgsParsing(getopts::Fail),
#[cfg(unix)]
#[error("Failed to turn polaris process into a daemon:\n\n{0}")]
Daemonize(daemonize::DaemonizeError),
Daemonize(daemonize::Error),
#[error("Could not create log directory `{0}`:\n\n{1}")]
LogDirectoryCreationError(PathBuf, std::io::Error),
#[error("Could not create log file `{0}`:\n\n{1}")]

View file

@ -12,6 +12,7 @@ use actix_web::{
FromRequest, HttpRequest, HttpResponse, Responder, ResponseError,
};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use base64::prelude::*;
use futures_util::future::err;
use percent_encoding::percent_decode_str;
use std::future::Future;
@ -531,7 +532,7 @@ async fn get_audio(
})
.await?;
let named_file = NamedFile::open(&audio_path).map_err(|_| APIError::AudioFileIOError)?;
let named_file = NamedFile::open(audio_path).map_err(|_| APIError::AudioFileIOError)?;
Ok(MediaFile::new(named_file))
}
@ -555,8 +556,7 @@ async fn get_thumbnail(
})
.await?;
let named_file =
NamedFile::open(&thumbnail_path).map_err(|_| APIError::ThumbnailFileIOError)?;
let named_file = NamedFile::open(thumbnail_path).map_err(|_| APIError::ThumbnailFileIOError)?;
Ok(MediaFile::new(named_file))
}
@ -671,7 +671,8 @@ async fn lastfm_link(
let base64_content = percent_decode_str(&payload.content).decode_utf8_lossy();
// Base64 decode
let popup_content = base64::decode(base64_content.as_bytes())
let popup_content = BASE64_STANDARD_NO_PAD
.decode(base64_content.as_bytes())
.map_err(|_| APIError::LastFMLinkContentBase64DecodeError)?;
// UTF-8 decode

View file

@ -162,6 +162,7 @@ impl From<ddns::Error> for APIError {
ddns::Error::Database(e) => APIError::Database(e),
ddns::Error::DatabaseConnection(e) => e.into(),
ddns::Error::UpdateQueryFailed(s) => APIError::DdnsUpdateQueryFailed(s),
ddns::Error::UpdateQueryTransport => APIError::DdnsUpdateQueryFailed(0),
}
}
}