Skip to content

Commit

Permalink
calculate files need to download or update
Browse files Browse the repository at this point in the history
  • Loading branch information
wznmickey committed Apr 21, 2024
1 parent 762d226 commit 9657f5a
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 19 deletions.
71 changes: 71 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ serde_json = "1.0.115"
lazy_static = "1.4.0"
serde = {version = "1.0.150", features = ["derive"]}
file = "1.1.2"
chrono = {version = "0.4.38"}
57 changes: 52 additions & 5 deletions src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,77 @@ pub struct Account {
config: Config,
remote_data: RemoteData,
course: Vec<Rc<Course>>,
folders: Vec<Folder>,
folders: Vec<Rc<Folder>>,
files: Vec<Rc<crate::course::File>>,
need_update_files: Vec<Rc<crate::course::File>>,
need_download_files: Vec<Rc<crate::course::File>>,
}

impl Account{
impl Account {
pub fn new(st: &str) -> Self {
let config = Config::read_file(st);
let remote_data = RemoteData::new(&config.key, &config.canvas_url);
let course = remote_data.get_course_list();
Account{
Account {
config,
remote_data,
course,
folders: Vec::new(),
files: Vec::new(),
need_download_files: Vec::new(),
need_update_files: Vec::new(),
}
}
pub fn get_folders (& mut self) -> () {
pub fn get_folders(&mut self) -> () {
for course in &self.course {
let mut ans = self.remote_data.get_folder_list(Rc::clone(&course));
self.folders.append(&mut ans);
}
}
pub fn create_folders(&self) -> () {
for folder in &self.folders {
create_dir_all(self.config.local_place.clone() + "/" +&folder.course.name + " "+ &folder.fullname).unwrap();
create_dir_all(
self.config.local_place.clone()
+ "/"
+ &folder.course.name
+ " "
+ &folder.fullname,
)
.unwrap();
}
}
pub fn get_files(&mut self) -> () {
for folder in &self.folders {
let mut ans = self
.remote_data
.get_file_list(Rc::clone(&folder), self.config.local_place.clone().into());
self.files.append(&mut ans);
}
}
pub fn calculate_files(&mut self) -> () {
let mut update_size = 0;
let mut download_size = 0;
for file in &self.files {
let temp = file.get_status();
match temp {
FileStatus::NeedUpdate => {
self.need_update_files.push(Rc::clone(file));
update_size += file.size;
}
FileStatus::NotExist => {
self.need_download_files.push(Rc::clone(file));
download_size += file.size;
}
FileStatus::Latest => {}
}
}
println!("update size: {}", update_size);
for file in &self.need_update_files {
println!("{:?}", file.my_full_path);
}
println!("download size: {}", download_size);
for file in &self.need_download_files {
println!("{:?}", file.my_full_path);
}
}
}
95 changes: 91 additions & 4 deletions src/course.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
use chrono::DateTime;
use chrono::Utc;
use futures::future::Remote;
use serde_json::Value;
use std::rc::Rc;
use std::cmp::max;
use std::os::unix::fs::MetadataExt;
use std::{
fs,
path::{Path, PathBuf},
rc::Rc,
};
pub enum FileStatus {
Latest,
NeedUpdate,
NotExist,
}
#[derive(Debug)]
pub struct Course {
pub id: i64,
Expand All @@ -23,13 +37,86 @@ pub struct Folder {
id: i64,
pub name: String,
pub fullname: String,
pub course: Rc<Course>
pub course: Rc<Course>,
pub filelink: String,
}
pub fn get_folder_from_json (x: &Value, c:Rc<Course>) -> Option<Folder> {
pub fn get_folder_from_json(x: &Value, c: Rc<Course>) -> Option<Folder> {
Some(Folder {
id: x["id"].as_i64()?,
name: x["name"].as_str()?.to_string(),
fullname: x["full_name"].as_str()?.to_string(),
course:c
course: c,
filelink: x["files_url"].as_str()?.to_string() + "?",
})
}

#[derive(Debug)]
pub struct File {
id: i64,
pub display_name: String,
pub filename: String,
pub url: String,
pub folder: Rc<Folder>,
pub content_type: String,
pub size: u64,
pub created_time: DateTime<Utc>,
pub updated_time: DateTime<Utc>,
pub modified_time: DateTime<Utc>,
pub my_full_path: PathBuf,
}
pub fn get_file_from_json(x: &Value, f: Rc<Folder>, mut path: PathBuf) -> Option<File> {
let temp = x["display_name"].as_str()?.to_string();
Some(File {
id: x["id"].as_i64()?,
my_full_path: {
path.push((&f.course.name).to_string() + " " + &f.fullname);
path.push(&temp);
path
},
display_name: temp,
filename: x["filename"].as_str()?.to_string(),
folder: f,
url: x["url"].as_str()?.to_string(),
content_type: x["content-type"].as_str()?.to_string(),
size: x["size"].as_u64()?,
created_time: DateTime::parse_from_str(x["created_at"].as_str()?, "%+")
.ok()?
.to_utc(),
updated_time: DateTime::parse_from_str(x["updated_at"].as_str()?, "%+")
.ok()?
.to_utc(),
modified_time: DateTime::parse_from_str(x["modified_at"].as_str()?, "%+")
.ok()?
.to_utc(),
})
}
impl File {
pub fn get_status(&self) -> FileStatus {
let x = fs::metadata(self.my_full_path.clone());
match x {
Ok(y) => {
let mod_time = chrono::DateTime::<Utc>::from(y.modified().unwrap());
let create_time = chrono::DateTime::<Utc>::from(y.created().unwrap());
let newest_local_time = if mod_time > create_time {
mod_time
} else {
create_time
};
let newest_remote_time = max(
max(self.created_time, self.modified_time),
self.updated_time,
);
if newest_local_time < newest_remote_time {
return FileStatus::NeedUpdate;
}
let local_size = y.len();
let remote_size = self.size;
if (local_size != remote_size) {
return FileStatus::NeedUpdate;
}
FileStatus::Latest
}
Err(_) => FileStatus::NotExist,
}
}
}
44 changes: 39 additions & 5 deletions src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use reqwest::blocking::Response;
use reqwest::header;
use reqwest::{self};
use serde_json::Value;
use std::path::PathBuf;
use std::rc::Rc;
pub struct RemoteData {
client: reqwest::blocking::Client,
Expand Down Expand Up @@ -69,8 +70,8 @@ impl RemoteData {
match course {
None => continue,
Some(course) => {
let boxed = Rc::new(course);
ans.push(boxed);
let rc = Rc::new(course);
ans.push(rc);
}
}
}
Expand All @@ -84,7 +85,7 @@ impl RemoteData {
}
ans
}
pub fn get_folder_list(&self, course: Rc<Course>) -> Vec<Folder> {
pub fn get_folder_list(&self, course: Rc<Course>) -> Vec<Rc<Folder>> {
let url = format!("{}/api/v1/courses/{}/folders?", self.url, course.id);
let responses = self.get_remote_resource(url.as_str());
let mut ans = Vec::new();
Expand All @@ -94,11 +95,44 @@ impl RemoteData {
let result: &Vec<Value> = result.as_array()?;
for i in result {
let folder = get_folder_from_json(i, Rc::clone(&course));
// println!("course={folder:?}");
// println!("folder={folder:?}");
match folder {
None => continue,
Some(folder) => {
ans.push(folder);
let rc = Rc::new(folder);
ans.push(rc);
}
}
}
Some(())
}() {
Some(_) => {}
None => {
break;
}
};
}
ans
}


pub fn get_file_list(&self, folder: Rc<Folder>,path:PathBuf) -> Vec<Rc<File>> {
let url = folder.filelink.as_str();
// println!("{url}");
let responses = self.get_remote_resource(url);
let mut ans = Vec::new();
for response in responses {
let _ = match || -> Option<()> {
let result: Value = response.json().ok()?;
let result: &Vec<Value> = result.as_array()?;
for i in result {
let file = get_file_from_json(i, Rc::clone(&folder),path.clone());
// println!("file={file:?}");
match file {
None => continue,
Some(file) => {
let rc = Rc::new(file);
ans.push(rc);
}
}
}
Expand Down
Loading

0 comments on commit 9657f5a

Please sign in to comment.