use canvasapi::prelude::*;
use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser, Debug)]
#[clap(author, version)]
struct Args {
#[clap(long)]
url: Option<String>,
#[clap(long)]
token: Option<String>,
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
Courses,
Assignments {
#[clap(value_parser)]
id: usize,
},
Course {
#[clap(value_parser)]
id: usize,
},
Users {
#[clap(value_parser)]
course_id: usize,
#[clap(short, long = "type", value_parser)]
type_: Option<Enrollment>,
},
Files {
#[clap(value_parser)]
id: usize,
#[clap(long, value_parser)]
out_dir: Option<std::path::PathBuf>,
},
SearchCourse {
#[clap(value_parser)]
search: String,
#[clap(long)]
public_only: bool,
#[clap(long)]
open_enrollment_only: bool,
},
Todo {
#[clap(value_parser)]
course_id: Option<usize>,
},
}
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Copy, Clone, ValueEnum)]
enum Enrollment {
Teacher,
Student,
StudentView,
TA,
Observer,
Designer,
}
impl From<Enrollment> for canvasapi::prelude::EnrollmentType {
fn from(val: Enrollment) -> Self {
match val {
Enrollment::Teacher => canvasapi::prelude::EnrollmentType::Teacher,
Enrollment::Student => canvasapi::prelude::EnrollmentType::Student,
Enrollment::StudentView => canvasapi::prelude::EnrollmentType::StudentView,
Enrollment::TA => canvasapi::prelude::EnrollmentType::TA,
Enrollment::Observer => canvasapi::prelude::EnrollmentType::Observer,
Enrollment::Designer => canvasapi::prelude::EnrollmentType::Designer,
}
}
}
#[tokio::main]
async fn main() {
dotenv::dotenv().ok().unwrap();
let args = Args::parse();
let base_url = if let Some(url) = args.url {
url.to_string()
} else {
std::env::var("CANVAS_BASE_URL")
.expect("Pass the Canvas URL as an environment variable, or pass it to the command.")
};
let canvas_token = if let Some(token) = args.token {
token
} else {
std::env::var("CANVAS_ACCESS_TOKEN")
.expect("Pass the Canvas access token using an environment variable, or pass it to the command.")
};
let canvas = CanvasInformation::new(&base_url, &canvas_token);
let data = match args.command {
Commands::Courses => {
let courses = Course::courses()
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
serde_json::to_string_pretty(&courses).unwrap()
}
Commands::Assignments { id } => {
let course = Canvas::get_course(id)
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
let assignments = course
.get_assignments()
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
serde_json::to_string_pretty(&assignments).unwrap()
}
Commands::Course { id } => {
let course = Canvas::get_course(id)
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
serde_json::to_string_pretty(&course).unwrap()
}
Commands::Users { course_id, type_ } => {
let course = Canvas::get_course(course_id)
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
let users = course.get_users().unwrap();
let users = if let Some(type_) = type_ {
users.add_parameter(<Enrollment as Into<EnrollmentType>>::into(type_))
} else {
users
};
let users = match users.fetch(&canvas).await {
Ok(users) => users.inner(),
Err(e) => {
println!("{}", e);
return;
}
};
serde_json::to_string_pretty(&users).unwrap()
}
Commands::Files { id, out_dir } => {
let course = Canvas::get_course(id)
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
let files = course
.get_files()
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
if let Some(out_dir) = out_dir.as_ref() {
if !out_dir.as_path().exists() {
std::fs::create_dir_all(out_dir.as_path()).unwrap();
}
}
for file in files {
let path = if let Some(ref out_dir) = out_dir {
out_dir.as_path().to_str().unwrap()
} else {
"."
};
file.download(&canvas, path).await.unwrap();
}
"".to_string()
}
Commands::SearchCourse {
search,
public_only,
open_enrollment_only,
} => {
let results = Canvas::search_course(search, public_only, open_enrollment_only)
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
serde_json::to_string_pretty(&results).unwrap()
}
Commands::Todo { course_id } => {
let results = Canvas::get_todo_items()
.unwrap()
.fetch(&canvas)
.await
.unwrap()
.inner();
let results = if let Some(course_id) = course_id {
results
.into_iter()
.filter(|item| item.course_id == Some(course_id as i64))
.collect()
} else {
results
};
serde_json::to_string_pretty(&results).unwrap()
}
};
println!("{data}");
}