stack_overflow_client/common/
mod.rs

1use serde::{Deserialize, Serialize};
2
3pub const STACK_APP_API: &str = "https://api.stackexchange.com";
4
5/// The Stack Exchange websites. Full list here: https://stackexchange.com/sites
6#[derive(Debug, Deserialize, Serialize)]
7pub enum StackSite {
8    AskUbuntu,
9    Meta,
10    ServerFault,
11    StackOverflow,
12    SuperUser,
13    Unix,
14}
15
16/// API Version isn't really supported and I should probably remove.
17/// The latest version as of 2023-05-25 is 2.3.
18/// You can check the latest version manually here: https://api.stackexchange.com/
19#[derive(Debug, Deserialize, Serialize)]
20pub enum ApiVersion {
21    V2_2,
22    V2_3,
23}
24
25#[derive(Debug, Deserialize, Serialize)]
26pub struct Response<T> {
27    pub items: Vec<T>,
28    pub has_more: bool,
29    pub quota_max: u32,
30    pub quota_remaining: u32,
31}
32
33impl ToString for StackSite {
34    fn to_string(&self) -> String {
35        match self {
36            StackSite::AskUbuntu => "askubuntu".to_string(),
37            StackSite::Meta => "meta".to_string(),
38            StackSite::ServerFault => "serverfault".to_string(),
39            StackSite::StackOverflow => "stackoverflow".to_string(),
40            StackSite::SuperUser => "superuser".to_string(),
41            StackSite::Unix => "unix".to_string(),
42        }
43    }
44}
45
46impl ToString for ApiVersion {
47    fn to_string(&self) -> String {
48        match self {
49            ApiVersion::V2_2 => "2.2".to_string(),
50            ApiVersion::V2_3 => "2.3".to_string(),
51        }
52    }
53}
54
55/// Stack API info object type describes a site in the Stack Exchange network.
56/// https://api.stackexchange.com/docs/types/info
57#[derive(Debug, Deserialize, Serialize)]
58pub struct Info {
59    pub site: Option<Site>,
60    pub new_active_users: u32,
61    pub total_users: u32,
62    pub badges_per_minute: f32,
63    pub total_badges: u32,
64    pub total_votes: u32,
65    pub total_comments: u32,
66    pub answers_per_minute: f32,
67    pub questions_per_minute: f32,
68    pub total_answers: u32,
69    pub total_accepted: u32,
70    pub total_unanswered: u32,
71    pub total_questions: u32,
72    pub api_revision: String,
73}
74
75/// This type represents a site in the Stack Exchange network.
76/// https://api.stackexchange.com/docs/types/site
77#[derive(Debug, Deserialize, Serialize)]
78pub struct Site {
79    pub name: String,
80    pub launch_date: u32,
81    pub open_beta_date: Option<u32>,
82    pub aliases: Option<Vec<String>>,
83    pub logo_url: String,
84    pub site_type: String,
85    pub related_sites: Option<Vec<RelatedSite>>,
86}
87
88/// This type represents a related site in the Stack Exchange network.
89/// https://api.stackexchange.com/docs/types/related-site
90#[derive(Debug, Deserialize, Serialize)]
91pub struct RelatedSite {
92    pub name: String,
93    pub relation: String,
94    pub api_site_parameter: String,
95    pub site_url: String,
96}
97
98#[cfg(test)]
99pub mod tests {
100    use super::*;
101
102    #[test]
103    fn test_info() {
104        let info_str = include_str!("../../api-examples/info.json");
105        let info: Info = serde_json::from_str(info_str).unwrap();
106        println!("{:?}", info);
107        assert_eq!(info.site.unwrap().name, "Example Site");
108        assert_eq!(info.new_active_users, 10);
109    }
110
111    #[test]
112    fn test_site() {
113        let site_str = include_str!("../../api-examples/site.json");
114        let site: Site = serde_json::from_str(site_str).unwrap();
115        println!("{:?}", site);
116        assert_eq!(site.name, "Example Site");
117        assert_eq!(site.launch_date, 1684474623);
118        assert_eq!(site.open_beta_date, Some(1684388223));
119    }
120
121    #[test]
122    pub fn test_related_site() {
123        let related_site_str =
124            include_str!("../../api-examples/related-site.json");
125        let related_site: RelatedSite =
126            serde_json::from_str(related_site_str).unwrap();
127        println!("{:?}", related_site);
128        assert_eq!(related_site.name, "Example Site");
129        assert_eq!(related_site.relation, "parent");
130    }
131}