-
Notifications
You must be signed in to change notification settings - Fork 300
/
Copy pathzulip.rs
106 lines (91 loc) · 2.79 KB
/
zulip.rs
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::HashMap;
use anyhow::{bail, Error};
use reqwest::blocking::{Client, ClientBuilder, Response};
use reqwest::Method;
use serde::Deserialize;
const ZULIP_BASE_URL: &str = "https://rust-lang.zulipchat.com/api/v1";
static TOKEN_VAR: &str = "ZULIP_TOKEN";
static USER_VAR: &str = "ZULIP_USER";
/// Access to the Zulip API
#[derive(Clone)]
pub(crate) struct ZulipApi {
client: Client,
auth: Option<(String, String)>,
}
impl ZulipApi {
/// Create a new `ZulipApi` instance
pub(crate) fn new() -> Self {
let username = std::env::var(USER_VAR).ok();
let token = std::env::var(TOKEN_VAR).ok();
let auth = match (username, token) {
(Some(u), Some(t)) => Some((u, t)),
_ => None,
};
Self {
client: ClientBuilder::new()
.user_agent(crate::USER_AGENT)
.build()
.unwrap(),
auth,
}
}
pub(crate) fn require_auth(&self) -> Result<(), Error> {
if self.auth.is_none() {
bail!("missing {USER_VAR} and/or {TOKEN_VAR} environment variables");
}
Ok(())
}
/// Get all users of the Rust Zulip instance
pub(crate) fn get_users(&self) -> Result<Vec<ZulipUser>, Error> {
let response = self
.req(Method::GET, "/users", None)?
.error_for_status()?
.json::<ZulipUsers>()?
.members;
Ok(response)
}
/// Get a single user of the Rust Zulip instance
pub(crate) fn get_user(&self, user_id: u64) -> Result<ZulipUser, Error> {
let response = self
.req(Method::GET, &format!("/users/{user_id}"), None)?
.error_for_status()?
.json::<ZulipOneUser>()?
.user;
Ok(response)
}
/// Perform a request against the Zulip API
fn req(
&self,
method: Method,
path: &str,
form: Option<HashMap<&str, &str>>,
) -> Result<Response, Error> {
let mut req = self
.client
.request(method, format!("{}{}", ZULIP_BASE_URL, path));
if let Some((username, token)) = &self.auth {
req = req.basic_auth(username, Some(token))
}
if let Some(form) = form {
req = req.form(&form);
}
Ok(req.send()?)
}
}
/// A collection of Zulip users, as returned from '/users'
#[derive(Deserialize)]
struct ZulipUsers {
members: Vec<ZulipUser>,
}
/// A collection of exactly one Zulip user, as returned from '/users/{user_id}'
#[derive(Deserialize)]
struct ZulipOneUser {
user: ZulipUser,
}
/// A single Zulip user
#[derive(Clone, Deserialize, PartialEq, Eq, Hash)]
pub(crate) struct ZulipUser {
pub(crate) user_id: u64,
#[serde(rename = "full_name")]
pub(crate) name: String,
}