Skip to main content

lavende_core/
config.rs

1pub mod sources {
2    pub mod amazonmusic {
3        use crate::config::sources::HttpProxyConfig;
4        use serde::{Deserialize, Serialize};
5        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
6        #[serde(default)]
7        pub struct AmazonMusicConfig {
8            pub enabled: bool,
9            #[serde(default = "default_search_limit")]
10            pub search_limit: usize,
11            pub proxy: Option<HttpProxyConfig>,
12            pub api_url: Option<String>,
13        }
14        fn default_search_limit() -> usize {
15            3
16        }
17    }
18    pub mod anghami {
19        use super::HttpProxyConfig;
20        use crate::config::sources::{default_limit_10, default_true};
21        use serde::{Deserialize, Serialize};
22        #[derive(Debug, Deserialize, Serialize, Clone)]
23        pub struct AnghamiConfig {
24            #[serde(default = "default_true")]
25            pub enabled: bool,
26            #[serde(default = "default_limit_10")]
27            pub search_limit: usize,
28            pub proxy: Option<HttpProxyConfig>,
29        }
30        impl Default for AnghamiConfig {
31            fn default() -> Self {
32                Self {
33                    enabled: true,
34                    search_limit: 10,
35                    proxy: None,
36                }
37            }
38        }
39    }
40    pub mod applemusic {
41        use super::HttpProxyConfig;
42        use crate::config::sources::{
43            default_country_code, default_five, default_true, default_zero,
44        };
45        use serde::{Deserialize, Serialize};
46        #[derive(Debug, Deserialize, Serialize, Clone)]
47        pub struct AppleMusicConfig {
48            #[serde(default = "default_true")]
49            pub enabled: bool,
50            #[serde(default = "default_country_code")]
51            pub country_code: String,
52            pub media_api_token: Option<String>,
53            #[serde(default = "default_zero")]
54            pub playlist_load_limit: usize,
55            #[serde(default = "default_zero")]
56            pub album_load_limit: usize,
57            #[serde(default = "default_five")]
58            pub playlist_page_load_concurrency: usize,
59            #[serde(default = "default_five")]
60            pub album_page_load_concurrency: usize,
61            pub proxy: Option<HttpProxyConfig>,
62        }
63        impl Default for AppleMusicConfig {
64            fn default() -> Self {
65                Self {
66                    enabled: true,
67                    country_code: default_country_code(),
68                    media_api_token: None,
69                    playlist_load_limit: 0,
70                    album_load_limit: 0,
71                    playlist_page_load_concurrency: 5,
72                    album_page_load_concurrency: 5,
73                    proxy: None,
74                }
75            }
76        }
77    }
78    pub mod audiomack {
79        use super::HttpProxyConfig;
80        use crate::config::sources::{default_limit_20, default_true};
81        use serde::{Deserialize, Serialize};
82        #[derive(Debug, Deserialize, Serialize, Clone)]
83        pub struct AudiomackConfig {
84            #[serde(default = "default_true")]
85            pub enabled: bool,
86            #[serde(default = "default_limit_20")]
87            pub search_limit: usize,
88            pub proxy: Option<HttpProxyConfig>,
89        }
90        impl Default for AudiomackConfig {
91            fn default() -> Self {
92                Self {
93                    enabled: true,
94                    search_limit: 20,
95                    proxy: None,
96                }
97            }
98        }
99    }
100    pub mod audius {
101        use super::HttpProxyConfig;
102        use crate::config::sources::{default_limit_10, default_limit_100, default_true};
103        use serde::{Deserialize, Serialize};
104        #[derive(Debug, Deserialize, Serialize, Clone)]
105        pub struct AudiusConfig {
106            #[serde(default = "default_true")]
107            pub enabled: bool,
108            #[serde(default = "default_limit_10")]
109            pub search_limit: usize,
110            #[serde(default = "default_limit_100")]
111            pub playlist_load_limit: usize,
112            #[serde(default = "default_limit_100")]
113            pub album_load_limit: usize,
114            #[serde(default)]
115            pub app_name: Option<String>,
116            pub proxy: Option<HttpProxyConfig>,
117        }
118        impl Default for AudiusConfig {
119            fn default() -> Self {
120                Self {
121                    enabled: true,
122                    search_limit: 10,
123                    playlist_load_limit: 100,
124                    album_load_limit: 100,
125                    app_name: None,
126                    proxy: None,
127                }
128            }
129        }
130    }
131    pub mod bandcamp {
132        use super::HttpProxyConfig;
133        use crate::config::sources::{default_limit_10, default_true};
134        use serde::{Deserialize, Serialize};
135        #[derive(Debug, Deserialize, Serialize, Clone)]
136        pub struct BandcampConfig {
137            #[serde(default = "default_true")]
138            pub enabled: bool,
139            #[serde(default = "default_limit_10")]
140            pub search_limit: usize,
141            pub proxy: Option<HttpProxyConfig>,
142        }
143        impl Default for BandcampConfig {
144            fn default() -> Self {
145                Self {
146                    enabled: true,
147                    search_limit: 10,
148                    proxy: None,
149                }
150            }
151        }
152    }
153    pub mod deezer {
154        use super::HttpProxyConfig;
155        use crate::config::sources::{default_false, default_true};
156        use serde::{Deserialize, Serialize};
157        #[derive(Debug, Deserialize, Serialize, Clone)]
158        pub struct DeezerConfig {
159            #[serde(default = "default_true")]
160            pub enabled: bool,
161            pub arls: Option<Vec<String>>,
162            pub master_decryption_key: Option<String>,
163            pub proxy: Option<HttpProxyConfig>,
164        }
165        impl Default for DeezerConfig {
166            fn default() -> Self {
167                Self {
168                    enabled: default_false(),
169                    arls: None,
170                    master_decryption_key: None,
171                    proxy: None,
172                }
173            }
174        }
175    }
176    pub mod flowery {
177        use crate::config::sources::{default_false, default_zero};
178        use serde::{Deserialize, Serialize};
179        #[derive(Debug, Deserialize, Serialize, Clone)]
180        pub struct FloweryConfig {
181            #[serde(default = "crate::config::sources::default_true")]
182            pub enabled: bool,
183            #[serde(default = "default_voice")]
184            pub voice: String,
185            #[serde(default = "default_false")]
186            pub translate: bool,
187            #[serde(default = "default_zero")]
188            pub silence: usize,
189            #[serde(default = "default_speed")]
190            pub speed: f32,
191            #[serde(default = "default_false")]
192            pub enforce_config: bool,
193        }
194        impl Default for FloweryConfig {
195            fn default() -> Self {
196                Self {
197                    enabled: false,
198                    voice: default_voice(),
199                    translate: false,
200                    silence: 0,
201                    speed: default_speed(),
202                    enforce_config: false,
203                }
204            }
205        }
206        fn default_voice() -> String {
207            "Salli".to_string()
208        }
209        fn default_speed() -> f32 {
210            1.0
211        }
212    }
213    pub mod gaana {
214        use super::HttpProxyConfig;
215        use crate::config::sources::{
216            default_limit_10, default_limit_20, default_limit_50, default_true,
217        };
218        use serde::{Deserialize, Serialize};
219        #[derive(Debug, Deserialize, Serialize, Clone)]
220        pub struct GaanaConfig {
221            #[serde(default = "default_true")]
222            pub enabled: bool,
223            pub proxy: Option<HttpProxyConfig>,
224            pub stream_quality: Option<String>,
225            #[serde(default = "default_limit_10")]
226            pub search_limit: usize,
227            #[serde(default = "default_limit_50")]
228            pub playlist_load_limit: usize,
229            #[serde(default = "default_limit_50")]
230            pub album_load_limit: usize,
231            #[serde(default = "default_limit_20")]
232            pub artist_load_limit: usize,
233        }
234        impl Default for GaanaConfig {
235            fn default() -> Self {
236                Self {
237                    enabled: true,
238                    proxy: None,
239                    stream_quality: None,
240                    search_limit: 10,
241                    playlist_load_limit: 50,
242                    album_load_limit: 50,
243                    artist_load_limit: 20,
244                }
245            }
246        }
247    }
248    pub mod google_tts {
249        use crate::config::sources::default_true;
250        use serde::{Deserialize, Serialize};
251        #[derive(Debug, Deserialize, Serialize, Clone)]
252        pub struct GoogleTtsConfig {
253            #[serde(default = "default_true")]
254            pub enabled: bool,
255            #[serde(default = "default_language")]
256            pub language: String,
257        }
258        impl Default for GoogleTtsConfig {
259            fn default() -> Self {
260                Self {
261                    enabled: true,
262                    language: default_language(),
263                }
264            }
265        }
266        fn default_language() -> String {
267            "en-US".to_string()
268        }
269    }
270    pub mod http {
271        use crate::config::sources::default_true;
272        use serde::{Deserialize, Serialize};
273        #[derive(Debug, Deserialize, Serialize, Clone)]
274        pub struct HttpSourceConfig {
275            #[serde(default = "default_true")]
276            pub enabled: bool,
277        }
278        impl Default for HttpSourceConfig {
279            fn default() -> Self {
280                Self { enabled: true }
281            }
282        }
283    }
284    pub mod jiosaavn {
285        use super::HttpProxyConfig;
286        use crate::config::sources::{
287            default_limit_10, default_limit_20, default_limit_50, default_true,
288        };
289        use serde::{Deserialize, Serialize};
290        #[derive(Debug, Deserialize, Serialize, Clone)]
291        pub struct JioSaavnConfig {
292            #[serde(default = "default_true")]
293            pub enabled: bool,
294            #[serde(rename = "apiUrl")]
295            pub api_url: Option<String>,
296            pub decryption: Option<JioSaavnDecryptionConfig>,
297            pub proxy: Option<HttpProxyConfig>,
298            #[serde(default = "default_limit_10")]
299            pub search_limit: usize,
300            #[serde(default = "default_limit_10")]
301            pub recommendations_limit: usize,
302            #[serde(default = "default_limit_50")]
303            pub playlist_load_limit: usize,
304            #[serde(default = "default_limit_50")]
305            pub album_load_limit: usize,
306            #[serde(default = "default_limit_20")]
307            pub artist_load_limit: usize,
308        }
309        impl Default for JioSaavnConfig {
310            fn default() -> Self {
311                Self {
312                    enabled: true,
313                    api_url: None,
314                    decryption: None,
315                    proxy: None,
316                    search_limit: 10,
317                    recommendations_limit: 10,
318                    playlist_load_limit: 50,
319                    album_load_limit: 50,
320                    artist_load_limit: 20,
321                }
322            }
323        }
324        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
325        pub struct JioSaavnDecryptionConfig {
326            #[serde(rename = "secretKey")]
327            pub secret_key: Option<String>,
328        }
329    }
330    pub mod lastfm {
331        use super::{default_false, default_limit_10};
332        use serde::{Deserialize, Serialize};
333        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
334        #[serde(default)]
335        pub struct LastFmConfig {
336            #[serde(default = "default_false")]
337            pub enabled: bool,
338            pub api_key: Option<String>,
339            #[serde(default = "default_limit_10")]
340            pub search_limit: usize,
341        }
342    }
343    pub mod local {
344        use crate::config::sources::default_true;
345        use serde::{Deserialize, Serialize};
346        #[derive(Debug, Deserialize, Serialize, Clone)]
347        pub struct LocalSourceConfig {
348            #[serde(default = "default_true")]
349            pub enabled: bool,
350        }
351        impl Default for LocalSourceConfig {
352            fn default() -> Self {
353                Self { enabled: true }
354            }
355        }
356    }
357    pub mod mixcloud {
358        use super::HttpProxyConfig;
359        use crate::config::sources::{default_limit_10, default_true};
360        use serde::{Deserialize, Serialize};
361        #[derive(Debug, Deserialize, Serialize, Clone)]
362        pub struct MixcloudConfig {
363            #[serde(default = "default_true")]
364            pub enabled: bool,
365            #[serde(default = "default_limit_10")]
366            pub search_limit: usize,
367            pub proxy: Option<HttpProxyConfig>,
368        }
369        impl Default for MixcloudConfig {
370            fn default() -> Self {
371                Self {
372                    enabled: true,
373                    search_limit: 10,
374                    proxy: None,
375                }
376            }
377        }
378    }
379    pub mod netease {
380        use super::HttpProxyConfig;
381        use crate::config::sources::{default_false, default_limit_10};
382        use serde::{Deserialize, Serialize};
383        #[derive(Debug, Deserialize, Serialize, Clone)]
384        pub struct NeteaseMusicConfig {
385            #[serde(default = "default_false")]
386            pub enabled: bool,
387            #[serde(default = "default_limit_10")]
388            pub search_limit: usize,
389            pub proxy: Option<HttpProxyConfig>,
390        }
391        impl Default for NeteaseMusicConfig {
392            fn default() -> Self {
393                Self {
394                    enabled: false,
395                    search_limit: 10,
396                    proxy: None,
397                }
398            }
399        }
400    }
401    pub mod pandora {
402        use super::HttpProxyConfig;
403        use crate::config::sources::{default_limit_10, default_limit_100, default_true};
404        use serde::{Deserialize, Serialize};
405        #[derive(Debug, Deserialize, Serialize, Clone)]
406        pub struct PandoraConfig {
407            #[serde(default = "default_true")]
408            pub enabled: bool,
409            pub proxy: Option<HttpProxyConfig>,
410            pub csrf_token: Option<String>,
411            #[serde(default = "default_limit_10")]
412            pub search_limit: usize,
413            #[serde(default = "default_limit_100")]
414            pub playlist_load_limit: usize,
415        }
416        impl Default for PandoraConfig {
417            fn default() -> Self {
418                Self {
419                    enabled: true,
420                    proxy: None,
421                    csrf_token: None,
422                    search_limit: 10,
423                    playlist_load_limit: 100,
424                }
425            }
426        }
427    }
428    pub mod qobuz {
429        use super::HttpProxyConfig;
430        use crate::config::sources::{
431            default_limit_10, default_limit_20, default_limit_50, default_limit_100, default_true,
432        };
433        use serde::{Deserialize, Serialize};
434        #[derive(Debug, Deserialize, Serialize, Clone)]
435        pub struct QobuzConfig {
436            #[serde(default = "default_true")]
437            pub enabled: bool,
438            pub user_token: Option<String>,
439            pub app_id: Option<String>,
440            pub app_secret: Option<String>,
441            pub proxy: Option<HttpProxyConfig>,
442            #[serde(default = "default_limit_10")]
443            pub search_limit: usize,
444            #[serde(default = "default_limit_100")]
445            pub playlist_load_limit: usize,
446            #[serde(default = "default_limit_50")]
447            pub album_load_limit: usize,
448            #[serde(default = "default_limit_20")]
449            pub artist_load_limit: usize,
450        }
451        impl Default for QobuzConfig {
452            fn default() -> Self {
453                Self {
454                    enabled: true,
455                    user_token: None,
456                    app_id: None,
457                    app_secret: None,
458                    proxy: None,
459                    search_limit: 10,
460                    playlist_load_limit: 100,
461                    album_load_limit: 50,
462                    artist_load_limit: 20,
463                }
464            }
465        }
466    }
467    pub mod reddit {
468        use crate::config::sources::HttpProxyConfig;
469        use serde::{Deserialize, Serialize};
470        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
471        #[serde(default)]
472        pub struct RedditConfig {
473            pub enabled: bool,
474            pub proxy: Option<HttpProxyConfig>,
475        }
476    }
477    pub mod shazam {
478        use super::HttpProxyConfig;
479        use crate::config::sources::{default_limit_10, default_true};
480        use serde::{Deserialize, Serialize};
481        #[derive(Debug, Deserialize, Serialize, Clone)]
482        pub struct ShazamConfig {
483            #[serde(default = "default_true")]
484            pub enabled: bool,
485            #[serde(default = "default_limit_10")]
486            pub search_limit: usize,
487            pub proxy: Option<HttpProxyConfig>,
488        }
489        impl Default for ShazamConfig {
490            fn default() -> Self {
491                Self {
492                    enabled: true,
493                    search_limit: 10,
494                    proxy: None,
495                }
496            }
497        }
498    }
499    pub mod soundcloud {
500        use super::HttpProxyConfig;
501        use crate::config::sources::{default_limit_10, default_limit_100, default_true};
502        use serde::{Deserialize, Serialize};
503        #[derive(Debug, Deserialize, Serialize, Clone)]
504        pub struct SoundCloudConfig {
505            #[serde(default = "default_true")]
506            pub enabled: bool,
507            pub client_id: Option<String>,
508            pub proxy: Option<HttpProxyConfig>,
509            #[serde(default = "default_limit_10")]
510            pub search_limit: usize,
511            #[serde(default = "default_limit_100")]
512            pub playlist_load_limit: usize,
513        }
514        impl Default for SoundCloudConfig {
515            fn default() -> Self {
516                Self {
517                    enabled: true,
518                    client_id: None,
519                    proxy: None,
520                    search_limit: 10,
521                    playlist_load_limit: 100,
522                }
523            }
524        }
525    }
526    pub mod spotify {
527        use super::HttpProxyConfig;
528        use crate::config::sources::{default_limit_10, default_limit_50, default_true};
529        use serde::{Deserialize, Serialize};
530        #[derive(Debug, Deserialize, Serialize, Clone)]
531        pub struct SpotifyConfig {
532            #[serde(default = "default_true")]
533            pub enabled: bool,
534            #[serde(default = "default_limit_6")]
535            pub playlist_load_limit: usize,
536            #[serde(default = "default_limit_6")]
537            pub album_load_limit: usize,
538            #[serde(default = "default_limit_10")]
539            pub search_limit: usize,
540            #[serde(default = "default_limit_10")]
541            pub recommendations_limit: usize,
542            #[serde(default = "default_limit_10")]
543            pub playlist_page_load_concurrency: usize,
544            #[serde(default = "default_limit_5")]
545            pub album_page_load_concurrency: usize,
546            #[serde(default = "default_limit_50")]
547            pub track_resolve_concurrency: usize,
548            pub proxy: Option<HttpProxyConfig>,
549        }
550        impl Default for SpotifyConfig {
551            fn default() -> Self {
552                Self {
553                    enabled: true,
554                    playlist_load_limit: 6,
555                    album_load_limit: 6,
556                    search_limit: 10,
557                    recommendations_limit: 10,
558                    playlist_page_load_concurrency: 10,
559                    album_page_load_concurrency: 5,
560                    track_resolve_concurrency: 50,
561                    proxy: None,
562                }
563            }
564        }
565        fn default_limit_6() -> usize {
566            6
567        }
568        fn default_limit_5() -> usize {
569            5
570        }
571    }
572    pub mod tidal {
573        use super::HttpProxyConfig;
574        use crate::config::sources::{
575            default_country_code, default_false, default_limit_20, default_limit_50,
576            default_tidal_quality, default_true,
577        };
578        use serde::{Deserialize, Serialize};
579        #[derive(Debug, Deserialize, Serialize, Clone)]
580        pub struct TidalConfig {
581            #[serde(default = "default_true")]
582            pub enabled: bool,
583            #[serde(default = "default_country_code")]
584            pub country_code: String,
585            #[serde(default = "default_tidal_quality")]
586            pub quality: String,
587            pub refresh_token: Option<String>,
588            #[serde(default = "default_false")]
589            pub get_oauth_token: bool,
590            #[serde(default = "default_limit_50")]
591            pub playlist_load_limit: usize,
592            #[serde(default = "default_limit_50")]
593            pub album_load_limit: usize,
594            #[serde(default = "default_limit_20")]
595            pub artist_load_limit: usize,
596            pub proxy: Option<HttpProxyConfig>,
597        }
598        impl Default for TidalConfig {
599            fn default() -> Self {
600                Self {
601                    enabled: true,
602                    country_code: default_country_code(),
603                    quality: default_tidal_quality(),
604                    refresh_token: None,
605                    get_oauth_token: false,
606                    playlist_load_limit: 50,
607                    album_load_limit: 50,
608                    artist_load_limit: 20,
609                    proxy: None,
610                }
611            }
612        }
613    }
614    pub mod twitch {
615        use crate::config::sources::HttpProxyConfig;
616        use serde::{Deserialize, Serialize};
617        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
618        #[serde(default)]
619        pub struct TwitchConfig {
620            pub enabled: bool,
621            pub client_id: Option<String>,
622            pub proxy: Option<HttpProxyConfig>,
623        }
624    }
625    pub mod vkmusic {
626        use super::HttpProxyConfig;
627        use crate::config::sources::{default_false, default_limit_10};
628        use serde::{Deserialize, Serialize};
629        #[derive(Debug, Deserialize, Serialize, Clone)]
630        pub struct VkMusicConfig {
631            #[serde(default = "default_false")]
632            pub enabled: bool,
633            pub user_token: Option<String>,
634            pub user_cookie: Option<String>,
635            #[serde(default = "default_limit_10")]
636            pub search_limit: usize,
637            #[serde(default = "default_one")]
638            pub playlist_load_limit: usize,
639            #[serde(default = "default_one")]
640            pub artist_load_limit: usize,
641            #[serde(default = "default_limit_10")]
642            pub recommendations_load_limit: usize,
643            pub proxy: Option<HttpProxyConfig>,
644        }
645        impl Default for VkMusicConfig {
646            fn default() -> Self {
647                Self {
648                    enabled: false,
649                    user_token: None,
650                    user_cookie: None,
651                    search_limit: 10,
652                    playlist_load_limit: 1,
653                    artist_load_limit: 1,
654                    recommendations_load_limit: 10,
655                    proxy: None,
656                }
657            }
658        }
659        fn default_one() -> usize {
660            1
661        }
662    }
663    pub mod yandexmusic {
664        use super::HttpProxyConfig;
665        use crate::config::sources::{default_false, default_limit_10, default_true};
666        use serde::{Deserialize, Serialize};
667        #[derive(Debug, Deserialize, Serialize, Clone)]
668        pub struct YandexMusicConfig {
669            #[serde(default = "default_true")]
670            pub enabled: bool,
671            pub access_token: Option<String>,
672            #[serde(default = "default_limit_6")]
673            pub playlist_load_limit: usize,
674            #[serde(default = "default_limit_6")]
675            pub album_load_limit: usize,
676            #[serde(default = "default_limit_6")]
677            pub artist_load_limit: usize,
678            pub proxy: Option<HttpProxyConfig>,
679            #[serde(default = "default_limit_10")]
680            pub search_limit: usize,
681        }
682        impl Default for YandexMusicConfig {
683            fn default() -> Self {
684                Self {
685                    enabled: default_false(),
686                    access_token: None,
687                    playlist_load_limit: 6,
688                    album_load_limit: 6,
689                    artist_load_limit: 6,
690                    proxy: None,
691                    search_limit: 10,
692                }
693            }
694        }
695        fn default_limit_6() -> usize {
696            6
697        }
698    }
699    pub mod youtube {
700        use crate::config::sources::{default_false, default_true};
701        use serde::{Deserialize, Serialize};
702        #[derive(Debug, Deserialize, Serialize, Clone)]
703        pub struct YouTubeConfig {
704            #[serde(default = "default_true")]
705            pub enabled: bool,
706            #[serde(default)]
707            pub clients: YouTubeClientsConfig,
708            #[serde(default)]
709            pub cipher: YouTubeCipherConfig,
710            #[serde(default)]
711            pub refresh_tokens: Vec<String>,
712            #[serde(default = "default_false")]
713            pub get_oauth_token: bool,
714        }
715        impl Default for YouTubeConfig {
716            fn default() -> Self {
717                Self {
718                    enabled: true,
719                    clients: YouTubeClientsConfig::default(),
720                    cipher: YouTubeCipherConfig::default(),
721                    refresh_tokens: Vec::new(),
722                    get_oauth_token: false,
723                }
724            }
725        }
726        #[derive(Debug, Deserialize, Serialize, Clone, Default)]
727        #[serde(default)]
728        pub struct YouTubeCipherConfig {
729            pub url: Option<String>,
730            pub token: Option<String>,
731        }
732        #[derive(Debug, Deserialize, Serialize, Clone)]
733        pub struct YouTubeClientsConfig {
734            #[serde(default = "default_search_clients")]
735            pub search: Vec<String>,
736            #[serde(default = "default_playback_clients")]
737            pub playback: Vec<String>,
738            #[serde(default = "default_resolve_clients")]
739            pub resolve: Vec<String>,
740        }
741        impl Default for YouTubeClientsConfig {
742            fn default() -> Self {
743                Self {
744                    search: default_search_clients(),
745                    playback: default_playback_clients(),
746                    resolve: default_resolve_clients(),
747                }
748            }
749        }
750        fn default_search_clients() -> Vec<String> {
751            vec![
752                "MUSIC_ANDROID".to_string(),
753                "MUSIC_WEB".to_string(),
754                "ANDROID".to_string(),
755                "WEB".to_string(),
756            ]
757        }
758        fn default_playback_clients() -> Vec<String> {
759            vec![
760                "TV".to_string(),
761                "ANDROID_MUSIC".to_string(),
762                "WEB".to_string(),
763                "IOS".to_string(),
764                "ANDROID_VR".to_string(),
765                "TV_CAST".to_string(),
766                "WEB_EMBEDDED".to_string(),
767            ]
768        }
769        fn default_resolve_clients() -> Vec<String> {
770            vec![
771                "WEB".to_string(),
772                "MUSIC_WEB".to_string(),
773                "ANDROID".to_string(),
774                "TVHTML5_SIMPLY".to_string(),
775            ]
776        }
777    }
778    pub use amazonmusic::*;
779    pub use anghami::*;
780    pub use applemusic::*;
781    pub use audiomack::*;
782    pub use audius::*;
783    pub use bandcamp::*;
784    pub use deezer::*;
785    pub use flowery::*;
786    pub use gaana::*;
787    pub use google_tts::*;
788    pub use http::*;
789    pub use jiosaavn::*;
790    pub use lastfm::*;
791    pub use local::*;
792    pub use mixcloud::*;
793    pub use netease::*;
794    pub use pandora::*;
795    pub use qobuz::*;
796    pub use reddit::*;
797    use serde::{Deserialize, Serialize};
798    pub use shazam::*;
799    pub use soundcloud::*;
800    pub use spotify::*;
801    pub use tidal::*;
802    pub use twitch::*;
803    pub use vkmusic::*;
804    pub use yandexmusic::*;
805    pub use youtube::*;
806    #[derive(Debug, Deserialize, Serialize, Clone, Default, PartialEq, Eq, Hash)]
807    pub struct HttpProxyConfig {
808        pub url: Option<String>,
809        pub username: Option<String>,
810        pub password: Option<String>,
811    }
812    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
813    #[serde(default)]
814    pub struct SourcesConfig {
815        pub youtube: Option<YouTubeConfig>,
816        pub spotify: Option<SpotifyConfig>,
817        pub amazonmusic: Option<AmazonMusicConfig>,
818        pub http: Option<HttpSourceConfig>,
819        pub local: Option<LocalSourceConfig>,
820        pub jiosaavn: Option<JioSaavnConfig>,
821        pub deezer: Option<DeezerConfig>,
822        pub applemusic: Option<AppleMusicConfig>,
823        pub gaana: Option<GaanaConfig>,
824        pub tidal: Option<TidalConfig>,
825        pub soundcloud: Option<SoundCloudConfig>,
826        pub audiomack: Option<AudiomackConfig>,
827        pub audius: Option<AudiusConfig>,
828        pub pandora: Option<PandoraConfig>,
829        pub qobuz: Option<QobuzConfig>,
830        pub anghami: Option<AnghamiConfig>,
831        pub shazam: Option<ShazamConfig>,
832        pub mixcloud: Option<MixcloudConfig>,
833        pub bandcamp: Option<BandcampConfig>,
834        pub twitch: Option<TwitchConfig>,
835        pub netease: Option<NeteaseMusicConfig>,
836        pub vkmusic: Option<VkMusicConfig>,
837        pub yandexmusic: Option<YandexMusicConfig>,
838        pub google_tts: Option<GoogleTtsConfig>,
839        pub flowery: Option<FloweryConfig>,
840        pub reddit: Option<RedditConfig>,
841        pub lastfm: Option<LastFmConfig>,
842    }
843    pub fn default_true() -> bool {
844        true
845    }
846    pub fn default_false() -> bool {
847        false
848    }
849    pub fn default_limit_10() -> usize {
850        10
851    }
852    pub fn default_limit_20() -> usize {
853        20
854    }
855    pub fn default_limit_50() -> usize {
856        50
857    }
858    pub fn default_limit_100() -> usize {
859        100
860    }
861    pub fn default_limit_3000() -> usize {
862        3000
863    }
864    pub fn default_country_code() -> String {
865        "us".to_string()
866    }
867    pub fn default_zero() -> usize {
868        0
869    }
870    pub fn default_five() -> usize {
871        5
872    }
873    pub fn default_tidal_quality() -> String {
874        "LOSSLESS".to_string()
875    }
876}
877pub mod filters {
878    use super::sources::default_true;
879    use serde::{Deserialize, Serialize};
880    #[derive(Debug, Deserialize, Serialize, Clone)]
881    pub struct FiltersConfig {
882        #[serde(default = "default_true")]
883        pub volume: bool,
884        #[serde(default = "default_true")]
885        pub equalizer: bool,
886        #[serde(default = "default_true")]
887        pub karaoke: bool,
888        #[serde(default = "default_true")]
889        pub timescale: bool,
890        #[serde(default = "default_true")]
891        pub tremolo: bool,
892        #[serde(default = "default_true")]
893        pub vibrato: bool,
894        #[serde(default = "default_true")]
895        pub distortion: bool,
896        #[serde(default = "default_true")]
897        pub rotation: bool,
898        #[serde(default = "default_true")]
899        pub channel_mix: bool,
900        #[serde(default = "default_true")]
901        pub low_pass: bool,
902        #[serde(default = "default_true")]
903        pub echo: bool,
904        #[serde(default = "default_true")]
905        pub high_pass: bool,
906        #[serde(default = "default_true")]
907        pub normalization: bool,
908        #[serde(default = "default_true")]
909        pub chorus: bool,
910        #[serde(default = "default_true")]
911        pub compressor: bool,
912        #[serde(default = "default_true")]
913        pub flanger: bool,
914        #[serde(default = "default_true")]
915        pub phaser: bool,
916        #[serde(default = "default_true")]
917        pub phonograph: bool,
918        #[serde(default = "default_true")]
919        pub reverb: bool,
920        #[serde(default = "default_true")]
921        pub spatial: bool,
922    }
923    impl Default for FiltersConfig {
924        fn default() -> Self {
925            Self {
926                volume: true,
927                equalizer: true,
928                karaoke: true,
929                timescale: true,
930                tremolo: true,
931                vibrato: true,
932                distortion: true,
933                rotation: true,
934                channel_mix: true,
935                low_pass: true,
936                echo: true,
937                high_pass: true,
938                normalization: true,
939                chorus: true,
940                compressor: true,
941                flanger: true,
942                phaser: true,
943                phonograph: true,
944                reverb: true,
945                spatial: true,
946            }
947        }
948    }
949    impl FiltersConfig {
950        pub fn is_enabled(&self, name: &str) -> bool {
951            match name {
952                "volume" => self.volume,
953                "equalizer" => self.equalizer,
954                "karaoke" => self.karaoke,
955                "timescale" => self.timescale,
956                "tremolo" => self.tremolo,
957                "vibrato" => self.vibrato,
958                "distortion" => self.distortion,
959                "rotation" => self.rotation,
960                "channel_mix" | "channelMix" => self.channel_mix,
961                "low_pass" | "lowPass" => self.low_pass,
962                "echo" => self.echo,
963                "high_pass" | "highPass" => self.high_pass,
964                "normalization" => self.normalization,
965                "chorus" => self.chorus,
966                "compressor" => self.compressor,
967                "flanger" => self.flanger,
968                "phaser" => self.phaser,
969                "phonograph" => self.phonograph,
970                "reverb" => self.reverb,
971                "spatial" => self.spatial,
972                _ => true,
973            }
974        }
975    }
976}
977pub mod lyrics {
978    use serde::{Deserialize, Serialize};
979    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
980    pub struct LyricsConfig {
981        #[serde(default)]
982        pub youtubemusic: bool,
983        #[serde(default)]
984        pub lrclib: bool,
985        #[serde(default)]
986        pub genius: bool,
987        #[serde(default)]
988        pub deezer: bool,
989        #[serde(default)]
990        pub musixmatch: bool,
991        #[serde(default)]
992        pub letrasmus: bool,
993        #[serde(default)]
994        pub yandex: bool,
995        #[serde(default)]
996        pub netease: bool,
997    }
998    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
999    #[serde(default)]
1000    pub struct YandexLyricsConfig {
1001        pub access_token: Option<String>,
1002    }
1003    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1004    #[serde(default)]
1005    pub struct YandexConfig {
1006        pub lyrics: Option<YandexLyricsConfig>,
1007    }
1008}
1009pub mod metrics {
1010    use serde::{Deserialize, Serialize};
1011    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1012    pub struct MetricsConfig {
1013        #[serde(default)]
1014        pub prometheus: PrometheusConfig,
1015    }
1016    #[derive(Debug, Deserialize, Serialize, Clone)]
1017    pub struct PrometheusConfig {
1018        #[serde(default)]
1019        pub enabled: bool,
1020        #[serde(default = "default_prometheus_endpoint")]
1021        pub endpoint: String,
1022    }
1023    impl Default for PrometheusConfig {
1024        fn default() -> Self {
1025            Self {
1026                enabled: false,
1027                endpoint: default_prometheus_endpoint(),
1028            }
1029        }
1030    }
1031    fn default_prometheus_endpoint() -> String {
1032        "/metrics".to_string()
1033    }
1034}
1035pub mod player {
1036    use serde::{Deserialize, Serialize};
1037    #[derive(Debug, Deserialize, Serialize, Clone)]
1038    pub struct PlayerConfig {
1039        #[serde(default = "default_stuck_threshold_ms")]
1040        pub stuck_threshold_ms: u64,
1041        #[serde(default = "default_buffer_duration_ms")]
1042        pub buffer_duration_ms: u64,
1043        #[serde(default = "default_frame_buffer_duration_ms")]
1044        pub frame_buffer_duration_ms: u64,
1045        #[serde(default)]
1046        pub resampling_quality: ResamplingQuality,
1047        #[serde(default = "default_opus_encoding_quality")]
1048        pub opus_encoding_quality: u8,
1049        #[serde(default)]
1050        pub tape: TapeConfig,
1051        #[serde(default)]
1052        pub mirrors: crate::config::server::MirrorsConfig,
1053    }
1054    #[derive(Debug, Deserialize, Serialize, Clone, Default, Copy, PartialEq)]
1055    #[serde(rename_all = "lowercase")]
1056    pub enum ResamplingQuality {
1057        Low,
1058        #[default]
1059        Medium,
1060        High,
1061    }
1062    #[derive(Debug, Deserialize, Serialize, Clone)]
1063    pub struct TapeConfig {
1064        #[serde(default)]
1065        pub tape_stop: bool,
1066        #[serde(default = "default_tape_stop_duration_ms")]
1067        pub tape_stop_duration_ms: u64,
1068        #[serde(default)]
1069        pub curve: TapeCurve,
1070    }
1071    #[derive(Debug, Deserialize, Serialize, Clone, Default, Copy, PartialEq)]
1072    #[serde(rename_all = "lowercase")]
1073    pub enum TapeCurve {
1074        Linear,
1075        Exponential,
1076        #[default]
1077        Sinusoidal,
1078    }
1079    impl TapeCurve {
1080        pub fn value(self, t: f32) -> f32 {
1081            match self {
1082                Self::Linear => t,
1083                Self::Exponential => t * t,
1084                Self::Sinusoidal => 0.5 * (1.0 - (t * std::f32::consts::PI).cos()),
1085            }
1086        }
1087    }
1088    impl Default for PlayerConfig {
1089        fn default() -> Self {
1090            Self {
1091                stuck_threshold_ms: default_stuck_threshold_ms(),
1092                buffer_duration_ms: default_buffer_duration_ms(),
1093                frame_buffer_duration_ms: default_frame_buffer_duration_ms(),
1094                resampling_quality: ResamplingQuality::default(),
1095                opus_encoding_quality: default_opus_encoding_quality(),
1096                tape: TapeConfig::default(),
1097                mirrors: crate::config::server::MirrorsConfig::default(),
1098            }
1099        }
1100    }
1101    impl Default for TapeConfig {
1102        fn default() -> Self {
1103            Self {
1104                tape_stop: false,
1105                tape_stop_duration_ms: default_tape_stop_duration_ms(),
1106                curve: TapeCurve::default(),
1107            }
1108        }
1109    }
1110    fn default_stuck_threshold_ms() -> u64 {
1111        10000
1112    }
1113    fn default_buffer_duration_ms() -> u64 {
1114        400
1115    }
1116    fn default_frame_buffer_duration_ms() -> u64 {
1117        5000
1118    }
1119    fn default_opus_encoding_quality() -> u8 {
1120        10
1121    }
1122    fn default_tape_stop_duration_ms() -> u64 {
1123        500
1124    }
1125}
1126pub mod server {
1127    use serde::{Deserialize, Serialize};
1128    #[derive(Debug, Deserialize, Serialize, Clone)]
1129    pub struct ServerConfig {
1130        #[serde(default = "default_address")]
1131        pub address: String,
1132        #[serde(default = "default_port")]
1133        pub port: u16,
1134        #[serde(default = "default_authorization")]
1135        pub authorization: String,
1136        #[serde(default = "default_player_update_interval")]
1137        pub player_update_interval: u64,
1138        #[serde(default = "default_stats_interval")]
1139        pub stats_interval: u64,
1140        #[serde(default = "default_websocket_ping_interval")]
1141        pub websocket_ping_interval: u64,
1142        #[serde(default = "default_max_event_queue_size")]
1143        pub max_event_queue_size: usize,
1144    }
1145    impl Default for ServerConfig {
1146        fn default() -> Self {
1147            Self {
1148                address: default_address(),
1149                port: default_port(),
1150                authorization: default_authorization(),
1151                player_update_interval: default_player_update_interval(),
1152                stats_interval: default_stats_interval(),
1153                websocket_ping_interval: default_websocket_ping_interval(),
1154                max_event_queue_size: default_max_event_queue_size(),
1155            }
1156        }
1157    }
1158    fn default_address() -> String {
1159        "127.0.0.1".to_string()
1160    }
1161    fn default_port() -> u16 {
1162        2333
1163    }
1164    fn default_authorization() -> String {
1165        "youshallnotpass".to_string()
1166    }
1167    fn default_max_event_queue_size() -> usize {
1168        100
1169    }
1170    fn default_player_update_interval() -> u64 {
1171        5
1172    }
1173    fn default_stats_interval() -> u64 {
1174        30
1175    }
1176    fn default_websocket_ping_interval() -> u64 {
1177        20
1178    }
1179    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1180    pub struct LoggingConfig {
1181        pub level: Option<String>,
1182        pub filters: Option<String>,
1183        pub file: Option<LogFileConfig>,
1184    }
1185    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1186    pub struct LogFileConfig {
1187        pub path: String,
1188        pub max_lines: u32,
1189        #[serde(default)]
1190        pub max_files: u32,
1191        #[serde(default)]
1192        pub rotate_daily: bool,
1193    }
1194    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1195    pub struct RoutePlannerConfig {
1196        #[serde(default)]
1197        pub enabled: bool,
1198        #[serde(default)]
1199        pub cidrs: Vec<String>,
1200        #[serde(default)]
1201        pub excluded_ips: Vec<String>,
1202    }
1203    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1204    #[serde(default)]
1205    pub struct MirrorsConfig {
1206        pub providers: Vec<String>,
1207        pub best_match: BestMatchConfig,
1208    }
1209    #[derive(Debug, Deserialize, Serialize, Clone)]
1210    #[serde(default)]
1211    pub struct BestMatchConfig {
1212        pub scoring: bool,
1213        pub throttled_prefixes: Vec<String>,
1214        pub min_similarity: f64,
1215        pub high_confidence: f64,
1216        pub immediate_use: f64,
1217        pub weight_title: f64,
1218        pub weight_artist: f64,
1219        pub weight_duration: f64,
1220        pub duration_tolerance_ms: u64,
1221    }
1222    impl Default for BestMatchConfig {
1223        fn default() -> Self {
1224            Self {
1225                scoring: true,
1226                throttled_prefixes: vec!["ytmsearch:".into(), "ytsearch:".into()],
1227                min_similarity: 0.50,
1228                high_confidence: 0.75,
1229                immediate_use: 0.88,
1230                weight_title: 0.50,
1231                weight_artist: 0.30,
1232                weight_duration: 0.20,
1233                duration_tolerance_ms: 3_000,
1234            }
1235        }
1236    }
1237    #[derive(Debug, Deserialize, Serialize, Clone, Default)]
1238    pub struct ConfigServerConfig {
1239        pub url: String,
1240        pub username: Option<String>,
1241        pub password: Option<String>,
1242    }
1243}
1244use crate::common::types::AnyResult;
1245pub use filters::*;
1246pub use lyrics::*;
1247pub use metrics::*;
1248pub use player::*;
1249use serde::Deserialize;
1250pub use server::*;
1251pub use sources::*;
1252use std::{fs, path::Path};
1253#[derive(Debug, Deserialize, Clone)]
1254pub struct AppConfig {
1255    pub server: ServerConfig,
1256    #[serde(default)]
1257    pub route_planner: RoutePlannerConfig,
1258    #[serde(default)]
1259    pub sources: SourcesConfig,
1260    #[serde(default)]
1261    pub lyrics: LyricsConfig,
1262    pub logging: Option<LoggingConfig>,
1263    #[serde(default)]
1264    pub filters: FiltersConfig,
1265    #[serde(default)]
1266    pub player: PlayerConfig,
1267    #[serde(default)]
1268    pub metrics: MetricsConfig,
1269    #[serde(default)]
1270    pub config_server: Option<ConfigServerConfig>,
1271}
1272impl AppConfig {
1273    pub async fn load() -> AnyResult<Self> {
1274        let config_path = if Path::new("config.toml").exists() {
1275            "config.toml"
1276        } else if Path::new("config.example.toml").exists() {
1277            "config.example.toml"
1278        } else {
1279            return Err("config.toml or config.example.toml not found — please create one from config.example.toml".into());
1280        };
1281        println!("Loading configuration from: {}", config_path);
1282        let raw = fs::read_to_string(config_path)?;
1283        if raw.is_empty() {
1284            return Err(format!("{} is empty", config_path).into());
1285        }
1286        let raw_val: toml::Value = toml::from_str(&raw)?;
1287        if let Some(cs_val) = raw_val.get("config_server") {
1288            let cs: ConfigServerConfig = cs_val.clone().try_into()?;
1289            let client = reqwest::Client::new();
1290            let mut request = client.get(&cs.url);
1291            if let (Some(u), Some(p)) = (&cs.username, &cs.password) {
1292                use base64::{Engine as _, engine::general_purpose};
1293                let auth = format!("{}:{}", u, p);
1294                let encoded = general_purpose::STANDARD.encode(auth);
1295                request = request.header("Authorization", format!("Basic {}", encoded));
1296            }
1297            let response = request.send().await?;
1298            if !response.status().is_success() {
1299                return Err(format!(
1300                    "Failed to fetch remote config: status {}",
1301                    response.status()
1302                )
1303                .into());
1304            }
1305            let remote_toml = response.text().await?;
1306            return Ok(toml::from_str(&remote_toml)?);
1307        }
1308        let config: Self = toml::from_str(&raw)?;
1309        Ok(config)
1310    }
1311}
1312impl Default for AppConfig {
1313    fn default() -> Self {
1314        Self {
1315            server: Default::default(),
1316            route_planner: Default::default(),
1317            sources: Default::default(),
1318            lyrics: Default::default(),
1319            logging: None,
1320            filters: Default::default(),
1321            player: Default::default(),
1322            metrics: Default::default(),
1323            config_server: None,
1324        }
1325    }
1326}