-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgithub_accounts.rs
More file actions
106 lines (97 loc) · 3.35 KB
/
github_accounts.rs
File metadata and controls
106 lines (97 loc) · 3.35 KB
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
use std::collections::BTreeMap;
use anyhow::Context;
use email_address::EmailAddress;
use serde::{Deserialize, Serialize};
use sheets::types::Sheet;
use crate::{
Error,
newtypes::{GithubLogin, Region, new_case_insensitive_email_address},
sheets::{SheetsClient, cell_string},
};
// TODO: Replace this with a serde implementation from a Google Sheet.
pub(crate) async fn get_trainees(
client: SheetsClient,
sheet_id: &str,
) -> Result<BTreeMap<GithubLogin, Trainee>, Error> {
const EXPECTED_SHEET_NAME: &str = "Form responses 1";
let data = client.get(sheet_id, true, &[]).await.map_err(|err| {
err.with_context(|| {
format!(
"Failed to get trainees github accounts sheet with id {}",
sheet_id
)
})
})?;
let sheet = data.body.sheets.into_iter().find(|sheet| {
if let Some(properties) = &sheet.properties {
properties.title == EXPECTED_SHEET_NAME
} else {
false
}
});
if let Some(sheet) = sheet {
let data = trainees_from_sheet(&sheet).map_err(|err| {
err.with_context(|| {
format!(
"Failed to read trainees from sheet {}",
sheet
.properties
.map(|properties| properties.title)
.as_deref()
.unwrap_or("<unknown>")
)
})
})?;
Ok(data)
} else {
Err(Error::Fatal(anyhow::anyhow!(
"Didn't find sheet '{}' in trainee GitHub sheet with id {}",
EXPECTED_SHEET_NAME,
sheet_id
)))
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Trainee {
pub name: String,
pub region: Region,
pub github_login: GithubLogin,
pub email: EmailAddress,
}
fn trainees_from_sheet(sheet: &Sheet) -> Result<BTreeMap<GithubLogin, Trainee>, Error> {
let mut trainees = BTreeMap::new();
for data in &sheet.data {
if data.start_column != 0 || data.start_row != 0 {
return Err(Error::Fatal(anyhow::anyhow!(
"Reading data from Google Sheets API - got data chunk that didn't start at row=0,column=0 - got row={},column={}",
data.start_row,
data.start_column
)));
}
for (row_index, row) in data.row_data.iter().enumerate() {
if row_index == 0 {
continue;
}
let cells = &row.values;
if cells.len() < 5 {
return Err(Error::Fatal(anyhow::anyhow!(
"Reading trainee data from Google Sheets API, row {} didn't have at least 5 columns",
row_index
)));
}
let github_login = GithubLogin::from(cell_string(&cells[3]));
let email = cell_string(&cells[4]);
trainees.insert(
github_login.clone(),
Trainee {
name: cell_string(&cells[1]),
region: Region(cell_string(&cells[2])),
github_login,
email: new_case_insensitive_email_address(&email)
.with_context(|| format!("Failed to parse trainee email {}", email))?,
},
);
}
}
Ok(trainees)
}