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}