mirror of
https://github.com/FliegendeWurst/KIT-ILIAS-downloader.git
synced 2024-08-28 04:04:18 +00:00
parent
07dc3a9be2
commit
cc7dcd6f9d
@ -4,14 +4,13 @@ use std::{collections::HashMap, error::Error as _, io::Write, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use cookie_store::CookieStore;
|
use cookie_store::CookieStore;
|
||||||
use ignore::gitignore::Gitignore;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use reqwest::{Client, IntoUrl, Proxy, Url};
|
use reqwest::{Client, IntoUrl, Proxy, Url};
|
||||||
use reqwest_cookie_store::CookieStoreMutex;
|
use reqwest_cookie_store::CookieStoreMutex;
|
||||||
use scraper::{ElementRef, Html, Selector};
|
use scraper::{ElementRef, Html, Selector};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{cli::Opt, queue, util::wrap_html, ILIAS_URL};
|
use crate::{cli::Opt, queue, util::wrap_html, ILIAS_URL, iliasignore::IliasIgnore};
|
||||||
|
|
||||||
pub mod course;
|
pub mod course;
|
||||||
pub mod exercise;
|
pub mod exercise;
|
||||||
@ -35,7 +34,7 @@ static CONTAINER_ITEM_TITLE: Lazy<Selector> =
|
|||||||
|
|
||||||
pub struct ILIAS {
|
pub struct ILIAS {
|
||||||
pub opt: Opt,
|
pub opt: Opt,
|
||||||
pub ignore: Gitignore,
|
pub ignore: IliasIgnore,
|
||||||
client: Client,
|
client: Client,
|
||||||
cookies: Arc<CookieStoreMutex>,
|
cookies: Arc<CookieStoreMutex>,
|
||||||
pub course_names: HashMap<String, String>,
|
pub course_names: HashMap<String, String>,
|
||||||
@ -61,7 +60,7 @@ impl ILIAS {
|
|||||||
pub async fn with_session(
|
pub async fn with_session(
|
||||||
opt: Opt,
|
opt: Opt,
|
||||||
session: Arc<CookieStoreMutex>,
|
session: Arc<CookieStoreMutex>,
|
||||||
ignore: Gitignore,
|
ignore: IliasIgnore,
|
||||||
course_names: HashMap<String, String>,
|
course_names: HashMap<String, String>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let mut builder = Client::builder()
|
let mut builder = Client::builder()
|
||||||
@ -88,7 +87,7 @@ impl ILIAS {
|
|||||||
opt: Opt,
|
opt: Opt,
|
||||||
user: &str,
|
user: &str,
|
||||||
pass: &str,
|
pass: &str,
|
||||||
ignore: Gitignore,
|
ignore: IliasIgnore,
|
||||||
course_names: HashMap<String, String>,
|
course_names: HashMap<String, String>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let cookie_store = CookieStore::default();
|
let cookie_store = CookieStore::default();
|
||||||
|
66
src/iliasignore.rs
Normal file
66
src/iliasignore.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use std::{path::{Path, PathBuf, Component}, ffi::OsString};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use ignore::gitignore::Gitignore;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IliasIgnore {
|
||||||
|
ignores: Vec<IgnoreFile>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IliasIgnore {
|
||||||
|
pub fn load(mut path: PathBuf) -> Result<Self> {
|
||||||
|
let mut ignores = Vec::new();
|
||||||
|
let mut prefix = Vec::new();
|
||||||
|
// example scenario:
|
||||||
|
// path = /KIT/ILIAS/SS 23/Next Generation Internet
|
||||||
|
// iliasignore in ILIAS/.iliasignore: prefix = SS 23/Next Generation Internet
|
||||||
|
// iliasignore in Next Generation Internet/.iliasignore: prefix = ""
|
||||||
|
loop {
|
||||||
|
let (ignore, error) = Gitignore::new(path.join(".iliasignore"));
|
||||||
|
if let Some(err) = error {
|
||||||
|
warning!(err);
|
||||||
|
}
|
||||||
|
if ignore.len() > 0 {
|
||||||
|
ignores.push(IgnoreFile {
|
||||||
|
ignore,
|
||||||
|
prefix: prefix.iter().fold(OsString::new(), |mut acc, el| {
|
||||||
|
acc.push(el);
|
||||||
|
acc.push("/");
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(last) = path.components().last() {
|
||||||
|
match last {
|
||||||
|
Component::Normal(name) => prefix.insert(0, name.to_owned()),
|
||||||
|
_ => break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
Ok(IliasIgnore {
|
||||||
|
ignores
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn should_ignore(&self, path: &Path, is_dir: bool) -> bool {
|
||||||
|
for ignore_file in &self.ignores {
|
||||||
|
let mut full_path = ignore_file.prefix.clone();
|
||||||
|
full_path.push(path.as_os_str());
|
||||||
|
let matched = ignore_file.ignore.matched(&full_path, is_dir);
|
||||||
|
if matched.is_whitelist() {
|
||||||
|
return false;
|
||||||
|
} else if matched.is_ignore() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct IgnoreFile {
|
||||||
|
ignore: Gitignore,
|
||||||
|
prefix: OsString
|
||||||
|
}
|
14
src/main.rs
14
src/main.rs
@ -25,6 +25,8 @@ mod cli;
|
|||||||
use cli::*;
|
use cli::*;
|
||||||
mod ilias;
|
mod ilias;
|
||||||
use ilias::*;
|
use ilias::*;
|
||||||
|
mod iliasignore;
|
||||||
|
use iliasignore::*;
|
||||||
use Object::*;
|
use Object::*;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod util;
|
mod util;
|
||||||
@ -38,7 +40,7 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_to_load_session(opt: Opt, ignore: Gitignore, course_names: HashMap<String, String>) -> Result<ILIAS> {
|
async fn try_to_load_session(opt: Opt, ignore: IliasIgnore, course_names: HashMap<String, String>) -> Result<ILIAS> {
|
||||||
let session_path = opt.output.join(".iliassession");
|
let session_path = opt.output.join(".iliassession");
|
||||||
let meta = tokio::fs::metadata(&session_path).await?;
|
let meta = tokio::fs::metadata(&session_path).await?;
|
||||||
let modified = meta.modified()?;
|
let modified = meta.modified()?;
|
||||||
@ -58,7 +60,7 @@ async fn try_to_load_session(opt: Opt, ignore: Gitignore, course_names: HashMap<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login(opt: Opt, ignore: Gitignore, course_names: HashMap<String, String>) -> Result<ILIAS> {
|
async fn login(opt: Opt, ignore: IliasIgnore, course_names: HashMap<String, String>) -> Result<ILIAS> {
|
||||||
// load .iliassession file
|
// load .iliassession file
|
||||||
if opt.keep_session {
|
if opt.keep_session {
|
||||||
match try_to_load_session(opt.clone(), ignore.clone(), course_names.clone())
|
match try_to_load_session(opt.clone(), ignore.clone(), course_names.clone())
|
||||||
@ -117,7 +119,7 @@ async fn real_main(mut opt: Opt) -> Result<()> {
|
|||||||
.context("failed to canonicalize output directory")?;
|
.context("failed to canonicalize output directory")?;
|
||||||
|
|
||||||
// load .iliasignore file
|
// load .iliasignore file
|
||||||
let (ignore, error) = Gitignore::new(opt.output.join(".iliasignore"));
|
let ignore = IliasIgnore::load(opt.output.clone())?;
|
||||||
|
|
||||||
// Load course_names.toml file
|
// Load course_names.toml file
|
||||||
let course_names_path = opt.output.join("course_names.toml");
|
let course_names_path = opt.output.join("course_names.toml");
|
||||||
@ -134,10 +136,6 @@ async fn real_main(mut opt: Opt) -> Result<()> {
|
|||||||
HashMap::new()
|
HashMap::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(err) = error {
|
|
||||||
warning!(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue::set_download_rate(opt.rate);
|
queue::set_download_rate(opt.rate);
|
||||||
|
|
||||||
let ilias = login(opt, ignore, course_names).await?;
|
let ilias = login(opt, ignore, course_names).await?;
|
||||||
@ -235,7 +233,7 @@ async fn process(ilias: Arc<ILIAS>, path: PathBuf, obj: Object) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// root path should not be matched
|
// root path should not be matched
|
||||||
if relative_path.parent().is_some() && ilias.ignore.matched(relative_path, obj.is_dir()).is_ignore() {
|
if relative_path.parent().is_some() && ilias.ignore.should_ignore(relative_path, obj.is_dir()) {
|
||||||
log!(1, "Ignored {}", relative_path.to_string_lossy());
|
log!(1, "Ignored {}", relative_path.to_string_lossy());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user