2018-02-10 10:26:26 +00:00
|
|
|
use std::fs;
|
2017-01-29 15:36:39 +00:00
|
|
|
use std::fs::File;
|
2021-01-23 21:37:41 +00:00
|
|
|
use std::io::{self, Error, ErrorKind, Read, Write};
|
|
|
|
use std::path::{Path, PathBuf};
|
2017-01-29 15:36:39 +00:00
|
|
|
|
2019-10-08 09:31:18 +00:00
|
|
|
use crate::authentication::Credentials;
|
|
|
|
use crate::spotify_id::FileId;
|
|
|
|
use crate::volume::Volume;
|
2017-01-29 15:36:39 +00:00
|
|
|
|
2017-01-31 08:21:30 +00:00
|
|
|
#[derive(Clone)]
|
2017-01-29 15:36:39 +00:00
|
|
|
pub struct Cache {
|
2020-07-24 21:18:29 +00:00
|
|
|
audio_root: PathBuf,
|
|
|
|
system_root: PathBuf,
|
2017-06-30 06:43:11 +00:00
|
|
|
use_audio_cache: bool,
|
2017-01-29 15:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-02-10 10:26:26 +00:00
|
|
|
fn mkdir_existing(path: &Path) -> io::Result<()> {
|
|
|
|
fs::create_dir(path).or_else(|err| {
|
|
|
|
if err.kind() == io::ErrorKind::AlreadyExists {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-01-29 15:36:39 +00:00
|
|
|
impl Cache {
|
2021-01-23 21:37:41 +00:00
|
|
|
pub fn new(
|
|
|
|
audio_location: PathBuf,
|
|
|
|
system_location: PathBuf,
|
|
|
|
use_audio_cache: bool,
|
|
|
|
) -> io::Result<Cache> {
|
|
|
|
if use_audio_cache {
|
|
|
|
mkdir_existing(&audio_location)?;
|
|
|
|
mkdir_existing(&audio_location.join("files"))?;
|
2020-08-02 08:52:09 +00:00
|
|
|
}
|
2021-01-23 21:37:41 +00:00
|
|
|
mkdir_existing(&system_location)?;
|
2017-01-29 15:36:39 +00:00
|
|
|
|
2021-01-23 21:37:41 +00:00
|
|
|
Ok(Cache {
|
2020-07-24 21:18:29 +00:00
|
|
|
audio_root: audio_location,
|
|
|
|
system_root: system_location,
|
2021-01-23 21:37:41 +00:00
|
|
|
use_audio_cache,
|
|
|
|
})
|
2017-01-29 15:36:39 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-16 04:07:04 +00:00
|
|
|
|
2017-01-29 15:36:39 +00:00
|
|
|
impl Cache {
|
2021-01-23 21:37:41 +00:00
|
|
|
fn open_credentials_file(&self) -> io::Result<File> {
|
|
|
|
File::open(self.system_root.join("credentials.json"))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_credentials(&self) -> io::Result<Credentials> {
|
|
|
|
let mut file = self.open_credentials_file()?;
|
|
|
|
let mut contents = String::new();
|
|
|
|
file.read_to_string(&mut contents)?;
|
|
|
|
serde_json::from_str(&contents).map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
2016-03-16 04:07:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 15:36:39 +00:00
|
|
|
pub fn credentials(&self) -> Option<Credentials> {
|
2021-01-23 21:37:41 +00:00
|
|
|
match self.read_credentials() {
|
|
|
|
Ok(c) => Some(c),
|
|
|
|
Err(e) => {
|
|
|
|
if e.kind() != ErrorKind::NotFound {
|
|
|
|
warn!("Error reading credentials from cache: {}", e);
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2016-03-16 04:07:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 15:36:39 +00:00
|
|
|
pub fn save_credentials(&self, cred: &Credentials) {
|
2021-01-23 21:37:41 +00:00
|
|
|
let result = self
|
|
|
|
.open_credentials_file()
|
|
|
|
.and_then(|mut file| write!(file, "{}", serde_json::to_string(cred)?));
|
|
|
|
if let Err(e) = result {
|
|
|
|
warn!("Cannot save credentials to cache: {}", e);
|
|
|
|
}
|
2016-03-16 04:07:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-24 21:18:29 +00:00
|
|
|
// cache volume to system_root/volume
|
2018-05-17 01:15:17 +00:00
|
|
|
impl Cache {
|
2021-01-23 21:37:41 +00:00
|
|
|
fn open_volume_file(&self) -> io::Result<File> {
|
|
|
|
File::open(self.system_root.join("volume"))
|
2018-05-17 01:15:17 +00:00
|
|
|
}
|
|
|
|
|
2021-01-23 21:37:41 +00:00
|
|
|
fn read_volume(&self) -> io::Result<Volume> {
|
|
|
|
let mut file = self.open_volume_file()?;
|
|
|
|
let mut contents = String::new();
|
|
|
|
file.read_to_string(&mut contents)?;
|
|
|
|
contents
|
|
|
|
.parse()
|
|
|
|
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn volume(&self) -> Option<Volume> {
|
|
|
|
match self.read_volume() {
|
|
|
|
Ok(v) => Some(v),
|
|
|
|
Err(e) => {
|
|
|
|
if e.kind() != ErrorKind::NotFound {
|
|
|
|
warn!("Error reading volume from cache: {}", e);
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2018-05-17 01:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn save_volume(&self, volume: Volume) {
|
2021-01-23 21:37:41 +00:00
|
|
|
let result = self
|
|
|
|
.open_volume_file()
|
|
|
|
.and_then(|mut file| write!(file, "{}", volume));
|
|
|
|
if let Err(e) = result {
|
|
|
|
warn!("Cannot save volume to cache: {}", e);
|
|
|
|
}
|
2018-05-17 01:15:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 15:36:39 +00:00
|
|
|
impl Cache {
|
|
|
|
fn file_path(&self, file: FileId) -> PathBuf {
|
|
|
|
let name = file.to_base16();
|
2020-07-26 14:11:32 +00:00
|
|
|
self.audio_root
|
|
|
|
.join("files")
|
|
|
|
.join(&name[0..2])
|
|
|
|
.join(&name[2..])
|
2017-01-29 15:36:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn file(&self, file: FileId) -> Option<File> {
|
2021-01-23 21:37:41 +00:00
|
|
|
File::open(self.file_path(file))
|
|
|
|
.map_err(|e| {
|
|
|
|
if e.kind() != ErrorKind::NotFound {
|
|
|
|
warn!("Error reading file from cache: {}", e)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.ok()
|
2017-01-29 15:36:39 +00:00
|
|
|
}
|
|
|
|
|
2021-01-23 21:37:41 +00:00
|
|
|
pub fn save_file<F: Read>(&self, file: FileId, contents: &mut F) -> io::Result<()> {
|
2017-06-30 06:43:11 +00:00
|
|
|
if self.use_audio_cache {
|
|
|
|
let path = self.file_path(file);
|
2021-01-23 21:37:41 +00:00
|
|
|
mkdir_existing(path.parent().unwrap())?;
|
2016-03-16 04:07:04 +00:00
|
|
|
|
2021-01-23 21:37:41 +00:00
|
|
|
let mut cache_file = File::create(path).or_else(|_| {
|
|
|
|
fs::remove_dir_all(&self.audio_root.join("files"))?;
|
|
|
|
mkdir_existing(&self.audio_root.join("files"))?;
|
2020-08-04 10:25:32 +00:00
|
|
|
|
|
|
|
let path = self.file_path(file);
|
2021-01-23 21:37:41 +00:00
|
|
|
mkdir_existing(path.parent().unwrap())?;
|
|
|
|
File::create(path)
|
|
|
|
})?;
|
|
|
|
|
|
|
|
io::copy(contents, &mut cache_file).or_else(|_| {
|
|
|
|
fs::remove_dir_all(&self.audio_root.join("files"))?;
|
|
|
|
mkdir_existing(&self.audio_root.join("files"))?;
|
2020-08-04 10:25:32 +00:00
|
|
|
|
|
|
|
let path = self.file_path(file);
|
2021-01-23 21:37:41 +00:00
|
|
|
mkdir_existing(path.parent().unwrap())?;
|
|
|
|
let mut file = File::create(path)?;
|
|
|
|
io::copy(contents, &mut file)
|
|
|
|
})?;
|
2017-06-30 06:43:11 +00:00
|
|
|
}
|
2021-01-23 21:37:41 +00:00
|
|
|
Ok(())
|
2017-01-29 15:36:39 +00:00
|
|
|
}
|
|
|
|
}
|