summaryrefslogtreecommitdiffstats
path: root/src/static_api.rs
blob: 164cfbe67643cf80e94cbdda39c4854a05e946ae (plain)
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
use crate::data::Data;
use rust_team_data::v1;
use failure::Error;
use log::info;
use std::path::Path;
use indexmap::IndexMap;

pub(crate) struct Generator<'a> {
    dest: &'a Path,
    data: &'a Data,
}

impl<'a> Generator<'a> {
    pub(crate) fn new(dest: &'a Path, data: &'a Data) -> Result<Generator<'a>, Error> {
        if dest.is_dir() {
            std::fs::remove_dir_all(&dest)?;
        }
        std::fs::create_dir_all(&dest)?;

        Ok(Generator { dest, data })
    }

    pub(crate) fn generate(&self) -> Result<(), Error> {
        self.generate_teams()?;
        self.generate_lists()?;
        Ok(())
    }

    fn generate_teams(&self) -> Result<(), Error> {
        let mut teams = IndexMap::new();

        for team in self.data.teams() {
            let leads = team.leads();
            let mut members = Vec::new();
            for github_name in &team.members(&self.data)? {
                if let Some(person) = self.data.person(github_name) {
                    members.push(v1::TeamMember {
                        name: person.name().into(),
                        github: (*github_name).into(),
                        is_lead: leads.contains(github_name),
                    });
                }
            }
            members.sort_by_key(|member| member.github.to_lowercase());
            members.sort_by_key(|member| !member.is_lead);

            let team_data = v1::Team {
                name: team.name().into(),
                kind: if team.is_wg() {
                    v1::TeamKind::WorkingGroup
                } else {
                    v1::TeamKind::Team
                },
                subteam_of: team.subteam_of().map(|st| st.into()),
                members,
                website_data: team.website_data().map(|ws| v1::TeamWebsite {
                    name: ws.name().into(),
                    description: ws.description().into(),
                    page: ws.page().unwrap_or(team.name()).into(),
                    email: ws.email().map(|e| e.into()),
                    repo: ws.repo().map(|e| e.into()),
                    discord: ws.discord().map(|i| v1::DiscordInvite {
                        channel: i.channel.into(),
                        url: i.url.into(),
                    }),
                    weight: ws.weight(),
                }),
            };

            self.add(&format!("v1/teams/{}.json", team.name()), &team_data)?;
            teams.insert(team.name().into(), team_data);
        }

        teams.sort_keys();
        self.add(
            "v1/teams.json",
            &v1::Teams { teams },
        )?;
        Ok(())
    }

    fn generate_lists(&self) -> Result<(), Error> {
        let mut lists = IndexMap::new();

        for list in self.data.lists()?.values() {
            let mut members = list.emails().to_vec();
            members.sort();
            lists.insert(list.address().to_string(), v1::List {
                address: list.address().to_string(),
                members,
            });
        }

        lists.sort_keys();
        self.add(
            "v1/lists.json",
            &v1::Lists { lists },
        )?;
        Ok(())
    }

    fn add<T: serde::Serialize>(&self, path: &str, obj: &T) -> Result<(), Error> {
        info!("writing API object {}...", path);
        let dest = self.dest.join(path);
        if let Some(parent) = dest.parent() {
            if !parent.exists() {
                std::fs::create_dir_all(parent)?;
            }
        }
        let json = serde_json::to_string_pretty(obj)?;
        std::fs::write(&dest, json.as_bytes())?;
        Ok(())
    }
}