Skip to content

Commit

Permalink
Add option to download the lichess db
Browse files Browse the repository at this point in the history
It will show up if the csv file isn't found.
Now it shouldn't be necessary to download and extract it manually
anymore.
  • Loading branch information
brianch committed Apr 20, 2024
1 parent a74d269 commit 061ef84
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 53 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ serde = "1.0.196"
serde_derive = "1.0.160"
serde_json = "1.0.113"
tokio = { version = "1.36.0", features = ["process", "io-std", "io-util", "sync"] }
reqwest = "0.12.4"
zstd = "0.13.1"
rodio = { version = "0.17.3", default-features = false, features = ["vorbis"] }
fluent-bundle = "0.15.2"
intl-memoizer = "0.5.1"
Expand Down
94 changes: 94 additions & 0 deletions src/download_db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use iced::futures::SinkExt;
use iced::{Subscription, subscription};
use std::fs::File;
use std::io::{Seek, Write};
use std::io::Cursor;
use std::fs::OpenOptions;
use zstd;

use crate::Message;

pub const LICHESS_ZST_FILE : &str = "puzzles/lichess_db_puzzle.csv.zst";

pub enum DownloadState {
StartDownload {
url: String,
path: String,
},
DownloadInProgress {
response: reqwest::Response,
file: File,
total: u64,
downloaded: u64,
},
Finished,
}

pub fn download_lichess_db(url: String, path: String) -> Subscription<Message> {
struct DownloadDb;

subscription::channel(
std::any::TypeId::of::<DownloadDb>(),
100,
|mut output| async move {
let mut state = DownloadState::StartDownload{ url , path: path.clone()};
loop {
match state {
DownloadState::StartDownload { url, path : _ } => {
let response = reqwest::get(url.clone()).await;

match response {
Ok(response) => {
if let Some(total) = response.content_length() {
let file = OpenOptions::new().append(true).read(true).create(true).open(LICHESS_ZST_FILE).expect("Unable to create lichess db archive.");
state = DownloadState::DownloadInProgress {
response,
file,
total,
downloaded: 0
};
} else {
state = DownloadState::Finished;
}
}
Err(_) => state = DownloadState::Finished,
}
} DownloadState::DownloadInProgress { mut response, mut file, total, downloaded } => {
match response.chunk().await {
Ok(Some(chunk)) => {
let downloaded = downloaded + chunk.len() as u64;
let percentage = (downloaded as f32 / total as f32) * 100.0;

let mut content = Cursor::new(chunk);
std::io::copy(&mut content, &mut file).expect("Error writing to the lichess db archive.");

let _ = output.send(Message::DownloadProgress(format!(" {:.2}%", percentage))).await;
state = DownloadState::DownloadInProgress {
response,
file,
total,
downloaded: downloaded,
};
}
Ok(None) => {
file.flush().expect("Error flushing lichess db archive file.");
file.rewind().expect("Error rewinding lichess db archive file.");

let target = std::fs::File::create(path.clone()).expect(&("Error creating file ".to_owned() + &path));
zstd::stream::copy_decode(file, target).unwrap();

let _ = std::fs::remove_file(LICHESS_ZST_FILE);
let _ = output.send(Message::DBDownloadFinished).await;

state = DownloadState::Finished;
}
Err(_) => state = DownloadState::Finished,
}
} DownloadState::Finished => {
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
}
}
}
}
)
}
Loading

0 comments on commit 061ef84

Please sign in to comment.