aboutsummaryrefslogtreecommitdiff
path: root/src/albums.rs
blob: 17966ff9b1b0e6d2fed6c429974067cedb022c8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use std::collections::HashSet;
use std::fs;

use expanduser::expanduser;
use walkdir::WalkDir;

use crate::config::Config;

pub fn load(config: &Config) -> HashSet<String> {
    let root = expanduser(&config.music_root).ok().filter(|p| p.is_dir());
    let Some(root_path) = root else {
        return HashSet::new();
    };

    let mut new_albums: HashSet<String> = HashSet::new();

    for entry in WalkDir::new(&root_path) {
        let entry = match entry {
            Ok(e) if e.path().is_dir() => e,
            _ => continue,
        };

        if !contains_audio(&entry, config) {
            continue;
        }

        if let Some(rel_str) = entry
            .path()
            .strip_prefix(&root_path)
            .ok()
            .and_then(|p| p.to_str())
        {
            new_albums.insert(rel_str.to_string());
        }
    }

    new_albums
}

fn contains_audio(entry: &walkdir::DirEntry, config: &Config) -> bool {
    fs::read_dir(entry.path()).ok().is_some_and(|mut entries| {
        entries.any(|e| {
            e.as_ref()
                .is_ok_and(|entry| is_audio_file(&entry.path(), config))
        })
    })
}

fn is_audio_file(path: &std::path::Path, config: &Config) -> bool {
    !path.is_dir()
        && path
            .extension()
            .and_then(|ext| ext.to_str())
            .map(str::to_lowercase)
            .is_some_and(|ext| config.audio_exts.contains(&format!(".{ext}")))
}