Add story module for deserializing meta

This commit is contained in:
Joakim Soderlund 2019-07-21 14:14:46 +00:00
parent 2207a6150a
commit 6e01dbea9f
4 changed files with 433 additions and 0 deletions

174
Cargo.lock generated
View file

@ -1,6 +1,180 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fimfareader"
version = "0.1.0"
dependencies = [
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-integer"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b"
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72"
"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
"checksum syn 0.15.40 (registry+https://github.com/rust-lang/crates.io-index)" = "bc945221ccf4a7e8c31222b9d1fc77aefdd6638eb901a6ce457a3dc29d4c31e8"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -6,3 +6,17 @@ edition = "2018"
[profile.release]
lto = true
[dependencies.chrono]
version = "*"
features = ["serde"]
[dependencies.hex]
version = "*"
[dependencies.serde]
version = "*"
features = ["derive"]
[dependencies.serde_json]
version = "*"

View file

@ -1,5 +1,7 @@
//! Main module.
pub mod story;
fn main() {
println!("Hellopaca, World!");
}

243
src/story.rs Normal file
View file

@ -0,0 +1,243 @@
//! Story meta.
use std::collections::BTreeMap;
use chrono::prelude::*;
use serde::de::Error;
use serde::{Deserialize, Deserializer};
use serde_json::Value;
#[derive(Clone, Debug, Deserialize)]
pub struct Story {
pub archive: Archive,
pub author: Author,
pub chapters: Vec<Chapter>,
pub color: Option<Color>,
pub completion_status: CompletionStatus,
pub content_rating: ContentRating,
pub cover_image: Option<CoverImage>,
pub date_modified: Option<DateTime<Utc>>,
pub date_published: Option<DateTime<Utc>>,
pub date_updated: Option<DateTime<Utc>>,
#[serde(deserialize_with = "null_to_html")]
pub description_html: String,
pub id: i64,
pub num_chapters: i32,
pub num_comments: i32,
pub num_dislikes: i32,
pub num_likes: i32,
pub num_views: i32,
pub num_words: i32,
pub prequel: Option<i64>,
pub published: bool,
pub rating: i32,
#[serde(deserialize_with = "null_to_text")]
pub short_description: String,
pub status: Status,
pub submitted: bool,
pub tags: Vec<Tag>,
#[serde(deserialize_with = "null_to_text")]
pub title: String,
pub total_num_views: i32,
pub url: String,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Archive {
pub date_checked: Option<DateTime<Utc>>,
pub date_created: Option<DateTime<Utc>>,
pub date_fetched: Option<DateTime<Utc>>,
pub date_updated: Option<DateTime<Utc>>,
pub path: String,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Author {
pub avatar: Option<BTreeMap<String, String>>,
pub bio_html: Option<String>,
pub date_joined: Option<DateTime<Utc>>,
#[serde(deserialize_with = "string_to_id")]
pub id: i64,
pub name: String,
pub num_blog_posts: Option<i32>,
pub num_followers: Option<i32>,
pub num_stories: Option<i32>,
pub url: String,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Chapter {
pub chapter_number: i32,
pub date_modified: Option<DateTime<Utc>>,
pub date_published: Option<DateTime<Utc>>,
pub id: i64,
pub num_views: i32,
pub num_words: i32,
pub published: bool,
#[serde(deserialize_with = "null_to_text")]
pub title: String,
pub url: String,
}
#[derive(Clone, Debug)]
pub struct Color {
red: u8,
green: u8,
blue: u8,
}
#[derive(Clone, Debug)]
pub enum CompletionStatus {
Cancelled,
Complete,
Hiatus,
Incomplete,
}
#[derive(Clone, Debug)]
pub enum ContentRating {
Everyone,
Mature,
Teen,
}
#[derive(Clone, Debug, Deserialize)]
pub struct CoverImage {
pub full: String,
pub large: String,
pub medium: String,
pub thumbnail: String,
}
#[derive(Clone, Debug)]
pub enum Status {
ApproveQueue,
NotVisible,
PostQueue,
Visible,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Tag {
pub id: i64,
pub name: String,
pub old_id: String,
pub r#type: String,
pub url: String,
}
pub fn null_to_html<'de, D>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
match Option::deserialize(d)? {
Some(text) => Ok(text),
None => Ok(String::from("<p></p>")),
}
}
pub fn null_to_text<'de, D>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
match Option::deserialize(d)? {
Some(text) => Ok(text),
None => Ok(String::from("")),
}
}
pub fn string_to_id<'de, D>(d: D) -> Result<i64, D::Error>
where
D: Deserializer<'de>,
{
let value = Value::deserialize(d)?;
if value.is_i64() {
Ok(value.as_i64().unwrap())
} else if value.is_string() {
value.as_str().unwrap().parse().map_err(|e| match e {
_ => Error::custom("Could not parse ID string."),
})
} else {
Err(Error::custom("Invalid type for ID value."))
}
}
impl<'de> Deserialize<'de> for Color {
fn deserialize<D>(d: D) -> Result<Color, D::Error>
where
D: Deserializer<'de>,
{
let object = Value::deserialize(d)?;
let text = object["hex"]
.as_str()
.ok_or(Error::custom("Color is missing hex value."))?;
let array = hex::decode(text).map_err(|e| match e {
_ => Error::custom("Color hex has invalid value."),
})?;
match array[..] {
[red, green, blue] => Ok(Color { red, green, blue }),
_ => Err(Error::custom("Color hex has invalid length.")),
}
}
}
impl CompletionStatus {
const FIELDS: &'static [&'static str] = &["cancelled", "complete", "hiatus", "incomplete"];
}
impl<'de> Deserialize<'de> for CompletionStatus {
fn deserialize<D>(d: D) -> Result<CompletionStatus, D::Error>
where
D: Deserializer<'de>,
{
match String::deserialize(d)?.as_ref() {
"cancelled" => Ok(CompletionStatus::Cancelled),
"complete" => Ok(CompletionStatus::Complete),
"hiatus" | "on hiatus" => Ok(CompletionStatus::Hiatus),
"incomplete" => Ok(CompletionStatus::Incomplete),
value => Err(Error::unknown_field(value, Self::FIELDS)),
}
}
}
impl ContentRating {
const FIELDS: &'static [&'static str] = &["everyone", "mature", "teen"];
}
impl<'de> Deserialize<'de> for ContentRating {
fn deserialize<D>(d: D) -> Result<ContentRating, D::Error>
where
D: Deserializer<'de>,
{
match String::deserialize(d)?.as_ref() {
"everyone" => Ok(ContentRating::Everyone),
"mature" => Ok(ContentRating::Mature),
"teen" => Ok(ContentRating::Teen),
value => Err(Error::unknown_field(value, Self::FIELDS)),
}
}
}
impl Status {
const FIELDS: &'static [&'static str] =
&["approve_queue", "not_visible", "post_queue", "visible"];
}
impl<'de> Deserialize<'de> for Status {
fn deserialize<D>(d: D) -> Result<Status, D::Error>
where
D: Deserializer<'de>,
{
match String::deserialize(d)?.as_ref() {
"approve_queue" => Ok(Status::ApproveQueue),
"not_visible" => Ok(Status::NotVisible),
"post_queue" => Ok(Status::PostQueue),
"visible" => Ok(Status::Visible),
value => Err(Error::unknown_field(value, Self::FIELDS)),
}
}
}