char-slop/tidal-dl
tidal ripper
git clone https://git.t4t.associates/char-slop/tidal-dl
d6e67a9
main
1use anyhow:: Result ; 2use base64::{ engine:: general_purpose:: STANDARD , Engine as _}; 3use serde::{ Deserialize , Serialize }; 4 5use crate :: pkce:: DEFAULT_PORT ; 6 7# [ derive ( Debug , Clone , Serialize , Deserialize )] 8pub struct Settings { 9# [ serde ( default = "default_download_path" )] 10pub download_path : String , 11# [ serde ( default = "default_port" )] 12pub auth_callback_port : u16 , 13} 14 15impl Default for Settings { 16fn default () ->Self { 17Self { 18download_path : default_download_path (), 19auth_callback_port : DEFAULT_PORT , 20} 21} 22} 23 24fn default_download_path () ->String { 25if let Some ( dir) = dirs:: download_dir () { 26return dir. to_string_lossy (). into_owned (); 27} 28if let Some ( home) = dirs:: home_dir () { 29if home. join ( "Downloads" ). is_dir () { 30return home. join ( "Downloads" ). to_string_lossy (). into_owned (); 31} 32} 33"./download" . to_string () 34} 35 36fn default_port () ->u16 { 37DEFAULT_PORT 38} 39 40# [ derive ( Debug , Clone , Default , Serialize , Deserialize )] 41# [ serde ( rename_all = "camelCase" )] 42pub struct Token { 43# [ serde ( default )] 44pub userid : Option < u64 >, 45# [ serde ( default , alias = "country_code" )] 46pub country_code : Option < String >, 47# [ serde ( default , alias = "access_token" )] 48pub access_token : Option < String >, 49# [ serde ( default , alias = "refresh_token" )] 50pub refresh_token : Option < String >, 51# [ serde ( default , alias = "expires_after" )] 52pub expires_after : i64 , 53} 54 55pub fn profile_path () -> std:: path:: PathBuf { 56crate :: pkce:: home_dir (). join ( ".tidal-dl.json" ) 57} 58 59pub fn token_path () -> std:: path:: PathBuf { 60crate :: pkce:: home_dir (). join ( ".tidal-dl.token.json" ) 61} 62 63pub fn load_settings () ->Settings { 64let path =profile_path (); 65let Ok ( text) = std:: fs:: read_to_string ( & path) else { 66return Settings :: default (); 67}; 68let mut settings: Settings = serde_json:: from_str ( & text). unwrap_or_default (); 69if matches! ( settings. download_path . as_str (), "./download/" |"./download" |"" ) { 70 settings. download_path =default_download_path (); 71} 72 settings 73} 74 75pub fn save_settings ( settings : & Settings ) ->Result <()> { 76let text = serde_json:: to_string_pretty ( settings) ?; 77 std:: fs:: write ( profile_path (), text) ?; 78Ok (()) 79} 80 81pub fn load_token () ->Token { 82let path =token_path (); 83let Ok ( raw) = std:: fs:: read ( & path) else { 84return Token :: default (); 85}; 86let text =STANDARD 87. decode ( & raw) 88. ok () 89. and_then ( |b|String :: from_utf8 ( b). ok ()) 90. unwrap_or_else ( ||String :: from_utf8_lossy ( & raw). into_owned ()); 91 serde_json:: from_str ( & text). unwrap_or_default () 92} 93 94pub fn save_token ( token : & Token ) ->Result <()> { 95let text = serde_json:: to_string ( token) ?; 96 std:: fs:: write ( token_path (), STANDARD . encode ( text)) ?; 97Ok (()) 98} 99 100pub fn clear_token () ->Result <()> { 101save_token ( & Token :: default ()) 102}