use super::error::*;
use super::fs::*;
use super::json::*;
use curl::easy::{Easy, List as CurlList};
use json::JsonValue;
use polars::prelude::{DataType, Field, Schema};
use std::iter::FromIterator as _;
pub fn is_valid_token_file(file_path: &str) -> Result<(), Error> {
let token_file = map_err(
open_csv(
file_path,
Some(Schema::from_iter(vec![Field::new(
"token".into(),
DataType::String,
)])),
Some(vec!["token"]),
),
&format!("Invalid token file {}", file_path),
)?;
if token_file.height() == 0 {
Error::new("Token file is empty").to_res()
} else {
for (i, token) in token_file
.column("token")
.unwrap()
.str()
.unwrap()
.iter()
.enumerate()
{
let mut headers: CurlList = CurlList::new();
let mut easy = Easy::new();
map_err(
easy.url("https://api.github.com").and_then(|_| {
easy.get(true)
.and_then(|_| {
headers.append(&format!("Authorization: token {}", token.unwrap()))
})
.and_then(|_| headers.append("User-Agent: Rust-curl"))
.and_then(|_| easy.http_headers(headers))
}),
"Could not make curl request",
)?;
if easy.perform().is_err() || easy.response_code().unwrap() != 200 {
Error::new(&format!("Token in line {} is invalid", i + 2)).to_res()?;
}
}
Ok(())
}
}
pub trait ToCSV: Default {
type Key;
fn to_csv(&self, key: Self::Key) -> String;
fn header() -> &'static [&'static str];
}
pub trait FromGitHub: ToCSV {
type Complement;
fn parse_date_time(json: &JsonValue, field: &str) -> Result<i64, Error> {
Ok(map_err(
chrono::NaiveDateTime::parse_from_str(
&get_field::<String>(json, field)?,
"%Y-%m-%dT%H:%M:%SZ",
),
&format!("Could not parse {} field epoch as a DateTime", field),
)?
.and_utc()
.timestamp())
}
fn parse_json(json: &json::JsonValue, complement: Self::Complement) -> Result<Self, Error>
where
Self: Sized;
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn valid_tokens() {
let token_path = Path::new("ghtokens.csv");
if token_path.exists() {
assert!(is_valid_token_file(token_path.to_str().unwrap()).is_ok());
}
}
#[test]
fn invalid_three_token_file() {
assert!(is_valid_token_file("tests/data/dummy_tokens.csv").is_err());
}
#[test]
fn invalid_non_existent_file() {
assert!(is_valid_token_file("tests/data/non_existent.csv").is_err());
}
#[test]
fn invalid_empty_file() {
assert!(is_valid_token_file("tests/data/empty.csv").is_err());
}
#[test]
fn invalid_title() {
assert!(is_valid_token_file("tests/data/invalid_token_title.csv").is_err());
}
#[test]
fn invalid_title_only_file() {
assert!(is_valid_token_file("tests/data/token_title_only.csv").is_err());
}
#[test]
fn two_token_same_line() {
assert!(is_valid_token_file("tests/data/two_tokens_same_line.csv").is_err());
}
#[test]
fn invalid_file() {
assert!(is_valid_token_file("tests/data/invalid_csv.csv").is_err());
}
}