mirror of
https://github.com/oSumAtrIX/free-librespot.git
synced 2025-12-19 18:04:20 +00:00
101 lines
2.9 KiB
Rust
101 lines
2.9 KiB
Rust
use std::path::PathBuf;
|
|
use std::io::Read;
|
|
use std::fs::File;
|
|
|
|
use util::{SpotifyId, FileId, ReadSeek, mkdir_existing};
|
|
use authentication::Credentials;
|
|
use audio_key::AudioKey;
|
|
|
|
use super::Cache;
|
|
|
|
pub struct DefaultCache {
|
|
environment: lmdb::Environment,
|
|
root: PathBuf,
|
|
}
|
|
|
|
impl DefaultCache {
|
|
pub fn new(location: PathBuf) -> Result<DefaultCache, ()> {
|
|
let env = lmdb::EnvBuilder::new().max_dbs(5).open(&location.join("db"), 0o755).unwrap();
|
|
|
|
mkdir_existing(&location).unwrap();
|
|
mkdir_existing(&location.join("files")).unwrap();
|
|
|
|
Ok(DefaultCache {
|
|
environment: env,
|
|
root: location
|
|
})
|
|
}
|
|
|
|
fn audio_keys(&self) -> MdbResult<lmdb::DbHandle> {
|
|
self.environment.create_db("audio-keys", lmdb::DbFlags::empty())
|
|
}
|
|
|
|
fn file_path(&self, file: FileId) -> PathBuf {
|
|
let name = file.to_base16();
|
|
self.root.join("files").join(&name[0..2]).join(&name[2..])
|
|
}
|
|
|
|
fn credentials_path(&self) -> PathBuf {
|
|
self.root.join("credentials.json")
|
|
}
|
|
}
|
|
|
|
impl Cache for DefaultCache {
|
|
fn get_audio_key(&self, track: SpotifyId, file: FileId) -> Option<AudioKey> {
|
|
let reader = self.environment.get_reader().unwrap();
|
|
let handle = self.audio_keys().unwrap();
|
|
let db = reader.bind(&handle);
|
|
|
|
let mut key = Vec::new();
|
|
key.extend_from_slice(&track.to_raw());
|
|
key.extend_from_slice(&file.0);
|
|
|
|
let value : Option<Vec<_>> = db.get(&key).ok();
|
|
value.and_then(|value| if value.len() == 16 {
|
|
let mut result = [0u8; 16];
|
|
result.clone_from_slice(&value);
|
|
Some(AudioKey(result))
|
|
} else {
|
|
None
|
|
})
|
|
}
|
|
|
|
fn put_audio_key(&self, track: SpotifyId, file: FileId, audio_key: AudioKey) {
|
|
let xact = self.environment.new_transaction().unwrap();
|
|
let handle = self.audio_keys().unwrap();
|
|
|
|
{
|
|
let db = xact.bind(&handle);
|
|
|
|
let mut key = Vec::new();
|
|
key.extend_from_slice(&track.to_raw());
|
|
key.extend_from_slice(&file.0);
|
|
|
|
db.set(&key, &audio_key.0.as_ref()).unwrap();
|
|
}
|
|
|
|
xact.commit().unwrap();
|
|
}
|
|
|
|
fn get_credentials(&self) -> Option<Credentials> {
|
|
let path = self.credentials_path();
|
|
Credentials::from_file(path)
|
|
}
|
|
fn put_credentials(&self, cred: &Credentials) {
|
|
let path = self.credentials_path();
|
|
cred.save_to_file(&path);
|
|
}
|
|
|
|
fn get_file(&self, file: FileId) -> Option<Box<ReadSeek>> {
|
|
File::open(self.file_path(file)).ok().map(|f| Box::new(f) as Box<ReadSeek>)
|
|
}
|
|
|
|
fn put_file(&self, file: FileId, contents: &mut Read) {
|
|
let path = self.file_path(file);
|
|
|
|
mkdir_existing(path.parent().unwrap()).unwrap();
|
|
|
|
let mut cache_file = File::create(path).unwrap();
|
|
::std::io::copy(contents, &mut cache_file).unwrap();
|
|
}
|
|
}
|