extern crate failure;
#[macro_use] extern crate failure_derive;
#[macro_use] extern crate serde_derive;
use reqwest as req;
pub mod mm {
#[derive(Fail, Debug)]
pub enum Error {
#[fail(display = "HTTP error: {}", err)]
HTTPError { err: reqwest::Error },
#[fail(display = "Error reading header: {}", err)]
EncodingError { err: http::header::ToStrError },
#[fail(display = "Missing header in response: {}", name)]
HeaderMissingError { name: String },
}
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Error {
Error::HTTPError { err }
}
}
impl From<http::header::ToStrError> for Error {
fn from(err: http::header::ToStrError) -> Error {
Error::EncodingError { err }
}
}
pub type Result<T> = core::result::Result<T, Error>;
}
#[derive(Serialize, Deserialize)]
struct Login {
login_id: String,
password: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct User {
id: String,
create_at: u64,
update_at: u64,
delete_at: u64,
username: String,
auth_data: String,
auth_service: String,
email: String,
nickname: String,
first_name: String,
last_name: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Team {
id: String,
display_name: String,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Channel {
id: String,
display_name: String,
name: String,
}
struct Session {
client: req::Client,
user: User,
uri: String,
token: String,
}
fn temp_password() -> Result<String, failure::Error> {
Ok(std::str::from_utf8(&std::process::Command::new("pass")
.args(&["mattermost/inf"])
.output()?.stdout)?.trim().to_string())
}
impl Session {
fn login(login: &Login, server: &str) -> mm::Result<Session> {
let uri = format!("{}/api/v4", server);
let client = req::Client::new();
let mut res = client.post(&format!("{}/users/login", uri))
.json(login)
.send()?;
let token_val = res.headers().get("token")
.ok_or(mm::Error::HeaderMissingError { name: "token".to_string() })?;
let token = format!("Bearer {}", token_val.to_str()?);
let user = res.json()?;
Ok(Session {
user,
client,
uri,
token,
})
}
fn get<T: for<'t> serde::Deserialize<'t>>(&self, path: String) -> mm::Result<T> {
Ok(self.client.get(&format!("{}/{}", self.uri, path))
.header("Content-Type", "application/json")
.header("Authorization", self.token.clone())
.send()?
.json()?)
}
fn get_me(&self) -> &User {
&self.user
}
fn get_teams(&self) -> mm::Result<Vec<Team>> {
self.get(format!("users/{}/teams", self.user.id))
}
fn get_channels_for_user(&self, user_id: &str, team_id: &str) -> mm::Result<Vec<Channel>> {
self.get(format!("users/{}/teams/{}/channels", user_id, team_id))
}
}
fn main() -> mm::Result<()> {
let password = temp_password().unwrap();
let login = Login {
login_id: "gdritter".to_string(),
password,
};
let s = Session::login(&login, "https://mm.infinitenegativeutility.com")?;
for t in s.get_teams()? {
let chans = s.get_channels_for_user(&s.get_me().id, &t.id)?;
println!("Got chans: {:#?}", chans);
}
Ok(())
}