use serde::{Deserialize};
use chrono::{Utc, Date, TimeZone};
use std::error::Error;
use reqwest;
#[derive(Debug, Deserialize)]
struct ComicRequest {
month: String,
num: u32,
link: String,
year: String,
news: String,
transcript: String,
alt: String,
img: String,
title: String,
day: String
}
#[derive(Debug)]
pub struct Comic {
pub title: String,
pub link: String,
pub num: u32,
pub img: String,
pub alt: String,
pub news: String,
pub transcript: String,
pub date: Date<Utc>
}
impl ComicRequest {
fn comic (self) -> Comic {
Comic {
title: self.title,
link: self.link,
num: self.num,
img: self.img,
alt: self.alt,
news: self.news,
transcript: self.transcript,
date: Utc.ymd(
self.year.parse::<i32>().unwrap(),
self.month.parse::<u32>().unwrap(),
self.day.parse::<u32>().unwrap()
)
}
}
}
impl Comic {
fn get_by_url (url: &str) -> Result<Comic, Box<dyn Error>> {
Ok(reqwest::get(url)?.json::<ComicRequest>()?.comic())
}
pub fn get (number: u32) -> Result<Comic, Box<dyn Error>> {
Comic::get_by_url(format!("https://xkcd.com/{}/info.0.json", number).as_str())
}
pub fn latest () -> Result<Comic, Box<dyn Error>> {
Comic::get_by_url("https://xkcd.com/info.0.json")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get () {
let data = Comic::get(10).unwrap();
assert_eq!(data.title, String::from("Pi Equals"));
assert_eq!(data.link, String::from(""));
assert_eq!(data.num, 10);
assert_eq!(data.img, String::from("https://imgs.xkcd.com/comics/pi.jpg"));
assert_eq!(data.alt, String::from("My most famous drawing, and one of the first I did for the site"));
assert_eq!(data.news, String::from(""));
assert_eq!(data.transcript, String::from("Pi = 3.141592653589793helpimtrappedinauniversefactory7108914..."));
assert_eq!(data.date, Utc.ymd(2006, 01, 01));
println!("{:?}", data);
}
#[test]
#[should_panic]
fn test_get_zero () {
Comic::get(0).unwrap();
}
#[test]
#[should_panic]
fn test_get_too_high () {
Comic::get(999999999).unwrap();
}
#[test]
#[should_panic]
fn test_get_bad_url () {
Comic::get_by_url("https://xkcd.com/100").unwrap();
}
#[test]
fn test_latest () {
Comic::latest().unwrap();
}
}