Skip to main content

selene_core/
lib.rs

1use std::{
2    path::{Path, PathBuf},
3    sync::LazyLock,
4};
5
6use directories::{BaseDirs, UserDirs};
7
8pub const PROGRAM_FS_NAME: &str = "selene";
9pub const PROGRAM_DISPLAY_NAME: &str = "Selene";
10
11#[cfg(feature = "lrclib")]
12pub mod lrclib;
13
14#[cfg(feature = "lastfm")]
15pub mod scrobbling;
16
17pub mod config;
18pub mod database;
19pub mod library;
20pub mod lyrics;
21pub mod media_container;
22pub mod utils;
23
24pub mod symphonia_helpers;
25
26#[cfg(any(feature = "lrclib", feature = "lastfm"))]
27static REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
28    reqwest::Client::builder()
29        .user_agent(format!(
30            "{PROGRAM_DISPLAY_NAME} v{ver} (https://codeberg.org/CrypticCreator/Selene)",
31            ver = env!("CARGO_PKG_VERSION")
32        ))
33        .build()
34        .unwrap()
35});
36
37static BASE_DIRS: LazyLock<Option<BaseDirs>> = LazyLock::new(BaseDirs::new);
38
39/// Returns the users `base_dirs`
40///
41/// # Panics
42///
43/// Panics if the internal `BASE_DIRS` static is [`None`]. This can only happen if the home directory is not found
44#[must_use]
45pub fn base_dirs() -> &'static BaseDirs {
46    BASE_DIRS.as_ref().unwrap()
47}
48
49#[must_use]
50pub fn config_dir() -> &'static Path {
51    &CONFIG_DIR
52}
53static CONFIG_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
54    let config_dir = base_dirs().config_dir();
55    if config_dir == base_dirs().data_dir() {
56        DATA_DIR.join("config")
57    } else {
58        config_dir.join(PROGRAM_FS_NAME)
59    }
60});
61
62#[must_use]
63pub fn data_dir() -> &'static Path {
64    &DATA_DIR
65}
66static DATA_DIR: LazyLock<PathBuf> = LazyLock::new(|| base_dirs().data_dir().join(PROGRAM_FS_NAME));
67
68#[must_use]
69pub fn state_dir() -> &'static Path {
70    &STATE_DIR
71}
72static STATE_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
73    base_dirs()
74        .state_dir()
75        .map_or(DATA_DIR.join("state"), |p| p.join(PROGRAM_FS_NAME))
76});
77
78#[must_use]
79pub fn cache_dir() -> PathBuf {
80    base_dirs().cache_dir().join(PROGRAM_FS_NAME)
81}
82
83#[must_use]
84pub fn runtime_dir() -> PathBuf {
85    base_dirs()
86        .runtime_dir()
87        .unwrap_or_else(|| base_dirs().cache_dir())
88        .join(PROGRAM_FS_NAME)
89}
90
91pub fn music_dir() -> Option<&'static Path> {
92    MUSIC_DIR.as_deref()
93}
94static MUSIC_DIR: LazyLock<Option<PathBuf>> = LazyLock::new(|| {
95    UserDirs::new().and_then(|user_dirs| user_dirs.audio_dir().map(|p| p.join("Selene Library")))
96});