feat(auth): Automatically find free port

* feat: add auth_port configuration option

Signed-off-by: Elias Assaf <elyas51000@gmail.com>

* feat(auth): Automatically find free port

---------

Signed-off-by: Elias Assaf <elyas51000@gmail.com>
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
Elias Assaf
2025-07-04 14:56:54 +03:00
committed by GitHub
parent b843c7e721
commit 128ca7cb2e
2 changed files with 21 additions and 2 deletions

View File

@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Automatically find free port for OAuth2 login flow
### Fixed
- Skip unplayable tracks

View File

@@ -1,3 +1,5 @@
use std::net::TcpListener;
use librespot_core::authentication::Credentials as RespotCredentials;
use librespot_core::cache::Cache;
use librespot_oauth::get_access_token;
@@ -7,7 +9,6 @@ use crate::config::{self, Config};
use crate::spotify::Spotify;
pub const SPOTIFY_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
pub const CLIENT_REDIRECT_URI: &str = "http://127.0.0.1:8989/login";
static OAUTH_SCOPES: &[&str] = &[
"playlist-modify",
@@ -35,6 +36,20 @@ static OAUTH_SCOPES: &[&str] = &[
"user-top-read",
];
pub fn find_free_port() -> Result<u16, String> {
let socket = TcpListener::bind("127.0.0.1:0").map_err(|e| e.to_string())?;
socket
.local_addr()
.map(|addr| addr.port())
.map_err(|e| e.to_string())
}
pub fn get_client_redirect_uri() -> String {
let auth_port = find_free_port().expect("Could not find free port");
let redirect_url = format!("http://127.0.0.1:{auth_port}/login");
redirect_url
}
/// Get credentials for use with librespot. This first tries to get cached credentials. If no cached
/// credentials are available it will initiate the OAuth2 login process.
pub fn get_credentials(configuration: &Config) -> Result<RespotCredentials, String> {
@@ -73,7 +88,7 @@ pub fn create_credentials() -> Result<RespotCredentials, String> {
println!("To login you need to perform OAuth2 authorization using your web browser\n");
get_access_token(
SPOTIFY_CLIENT_ID,
CLIENT_REDIRECT_URI,
&get_client_redirect_uri(),
OAUTH_SCOPES.to_vec(),
)
.map(|token| RespotCredentials::with_access_token(token.access_token))