1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! Gallery image specification
use crate::model::common::AccountID;
use serde::{Deserialize, Serialize};
use std::fmt;
use time::{serde::timestamp, OffsetDateTime};
use url::Url;
/// Gallery image unique ID
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
pub struct GalleryImageID(String);
impl<U> From<U> for GalleryImageID
where
U: Into<String>,
{
fn from(v: U) -> Self {
GalleryImageID(v.into())
}
}
impl fmt::Display for GalleryImageID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
/// Gallery image
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
// #[serde(deny_unknown_fields)]
pub struct GalleryImage {
/// The username of the account that uploaded it, or null.
pub account_url: Option<String>,
/// The account ID of the account that uploaded it, or null.
pub account_id: Option<AccountID>,
/// TODO: missing from API model
pub ad_type: Option<serde_json::Value>,
/// TODO: missing from API model
pub ad_url: Option<serde_json::Value>,
/// Is the image animated
pub animated: bool,
/// Bandwidth consumed by the image in bytes
pub bandwidth: u64,
/// Number of comments on the gallery image.
pub comment_count: Option<u64>,
/// Time inserted into the gallery, epoch time
#[serde(with = "timestamp")]
pub datetime: OffsetDateTime,
/// OPTIONAL, the deletehash, if you're logged in as the image owner
#[serde(rename = "deletehash")]
pub delete_hash: Option<String>,
/// Description of the image.
pub description: Option<String>,
/// Number of downvotes for the image
pub downs: Option<u64>,
/// TODO: missing from API model
pub edited: Option<serde_json::Value>,
/// Indicates if the current user favorited the image. Defaults to false if not signed in.
pub favorite: Option<bool>,
/// Indicates the number of users that have favorited the album.
pub favorite_count: Option<u64>,
/// OPTIONAL, The .gifv link. Only available if the image is animated and type is 'image/gif'.
pub gifv: Option<Url>,
/// TODO: missing from API model
pub has_sound: Option<bool>,
/// The height of the image in pixels
pub height: u64,
/// The ID for the image
pub id: String,
/// TODO: missing from API model
pub in_gallery: Option<bool>,
/// Indicates if the image is in the most viral gallery or not.
pub in_most_viral: Option<bool>,
/// If it's an album or not
pub is_album: Option<bool>,
/// TODO: missing from API model
pub is_ad: Option<bool>,
/// The direct link to the the image. (Note: if fetching an animated GIF that was over 20MB in original size, a .gif thumbnail will be returned)
pub link: Option<Url>,
/// OPTIONAL, Whether the image has a looping animation. Only available if the image is animated and type is 'image/gif'.
pub looping: Option<bool>,
/// Image MIME type.
#[serde(rename = "type")]
pub mime_type: Option<String>,
/// OPTIONAL, The direct link to the .mp4. Only available if the image is animated and type is 'image/gif'.
pub mp4: Option<Url>,
/// OPTIONAL, The Content-Length of the .mp4. Only available if the image is animated and type is 'image/gif'. Note that a zero value (0) is possible if the video has not yet been generated
pub mp4_size: Option<u64>,
/// Indicates if the image has been marked as nsfw or not. Defaults to null if information is not available.
pub nsfw: Option<bool>,
/// Upvotes minus downvotes
pub points: Option<i64>,
/// Imgur popularity score
pub score: Option<i64>,
/// If the image has been categorized by our backend then this will contain the section the image belongs in. (funny, cats, adviceanimals, wtf, etc)
pub section: Option<String>,
/// The size of the image in bytes
pub size: u64,
/// The title of the image.
pub title: Option<String>,
/// Topic of the gallery image.
pub topic: Option<String>,
/// Topic ID of the gallery image.
pub topic_id: Option<u64>,
/// Upvotes for the image
pub ups: Option<u64>,
/// The number of image views
pub views: u64,
/// The current user's vote on the album. null if not signed in or if the user hasn't voted on it.
pub vote: Option<String>,
/// The width of the image in pixels
pub width: u64,
}
#[cfg(test)]
mod test {
use std::error::Error;
use crate::model::basic::Basic;
use crate::model::gallery_image::GalleryImage;
#[test]
fn test_deserialize_gallery_image_local() -> Result<(), Box<dyn Error>> {
let res = r#"{
"data": {
"id": "OUHDm",
"title": "My most recent drawing. Spent over 100 hours. I'm pretty proud of it.",
"description": null,
"datetime": 1349051625,
"type": "image/jpeg",
"animated": false,
"width": 2490,
"height": 3025,
"size": 618969,
"views": 625622,
"comment_count": 10,
"bandwidth": 387240623718,
"vote": null,
"section": "pics",
"account_url": "saponifi3d",
"account_id": 384077,
"ups": 1889,
"downs": 58,
"points": 1831,
"score": 18935622,
"is_album": false
},
"success" : true,
"status" : 200
}"#;
let data = serde_json::from_str::<Basic<GalleryImage>>(res)?;
println!("{:#?}", data);
Ok(())
}
}