summaryrefslogtreecommitdiff
path: root/src/strava.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/strava.rs')
-rw-r--r--src/strava.rs108
1 files changed, 85 insertions, 23 deletions
diff --git a/src/strava.rs b/src/strava.rs
index 6be5466..284d8b1 100644
--- a/src/strava.rs
+++ b/src/strava.rs
@@ -1,4 +1,6 @@
+use crate::error;
use crate::error::Error;
+use crate::models;
use chrono::serde::ts_seconds;
use chrono::DateTime;
use chrono::Utc;
@@ -8,53 +10,113 @@ use serde::Serialize;
use serde_json::from_value;
use serde_json::Value;
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Token {
+ #[serde(with = "ts_seconds")]
+ pub expires_at: DateTime<Utc>,
+ pub refresh_token: String,
+ pub access_token: String,
+}
+
+impl Token {
+ pub fn update_model(&self, out: &mut models::StravaToken) {
+ out.expires_at = self.expires_at.clone();
+ out.refresh_token = self.refresh_token.clone();
+ out.access_token = self.access_token.clone();
+ }
+}
+
+impl From<&models::StravaToken> for Token {
+ fn from(t: &models::StravaToken) -> Token {
+ Token {
+ expires_at: t.expires_at,
+ refresh_token: t.refresh_token.clone(),
+ access_token: t.access_token.clone(),
+ }
+ }
+}
+
pub trait StravaApi {
- fn get<T: Serialize + ?Sized>(&self, method: &str, access_token: &str, parasm: &T) -> Result<Value, Error>;
+ fn get<T: Serialize + ?Sized>(
+ &self,
+ method: &str,
+ access_token: &str,
+ parasm: &T,
+ ) -> Result<Value, Error>;
+
+ fn refresh_token(
+ &self,
+ token: &Token) -> Result<Token, Error>;
}
pub struct StravaImpl {
client: reqwest::blocking::Client,
base_url: String,
+ api_url: String,
+ client_id: String,
+ client_secret: String,
}
impl StravaImpl {
- pub fn new() -> StravaImpl {
+ pub fn new(client_id: String, client_secret: String) -> StravaImpl {
StravaImpl {
client: reqwest::blocking::Client::new(),
- base_url: "https://www.strava.com/api/v3".to_string(),
+ base_url: "https://www.strava.com".to_string(),
+ api_url: "/api/v3".to_string(),
+ client_id,
+ client_secret,
}
}
}
impl StravaApi for StravaImpl {
- fn get<T: Serialize + ?Sized>(&self, method: &str, access_token: &str,
- params: &T) -> Result<Value, Error> {
- let uri = format!("{}{}", self.base_url, method);
- let response = self.client.get(&uri)
+ fn get<T: Serialize + ?Sized>(
+ &self,
+ method: &str,
+ access_token: &str,
+ params: &T,
+ ) -> Result<Value, Error> {
+ let uri = format!("{}{}{}", self.base_url, self.api_url, method);
+ let response = self
+ .client
+ .get(&uri)
.bearer_auth(access_token)
.query(params)
.send()?;
info!("StravaApi::get({}) returned {:?}", method, response);
- let json = response.json()?;
+ let status = response.status();
+ let json: Value = response.json()?;
+
+ if !status.is_success() {
+ return Err(From::from(error::StravaApiError::new(status, json)));
+ }
Ok(json)
}
-}
-#[derive(Serialize, Deserialize, Debug)]
-pub struct AthleteSummary {
- id: i64,
- username: String,
- firstname: String,
- lastname: String,
-}
+ fn refresh_token(
+ &self,
+ token: &Token) -> Result<Token, Error> {
+ let uri = format!("{}{}{}", self.base_url, self.api_url, "/oauth/token");
+ let params = [
+ ("client_id", self.client_id.as_str()),
+ ("client_secret", self.client_secret.as_str()),
+ ("grant_type", "refresh_token"),
+ ("refresh_token", token.refresh_token.as_str()),
+ ];
+ let response = self
+ .client
+ .post(&uri)
+ .form(&params)
+ .send()?;
+ info!("StravaApi::refresh_token returned {:?}", response);
+ let status = response.status();
+ let json: Value = response.json()?;
-#[derive(Serialize, Deserialize, Debug)]
-pub struct Token {
- #[serde(with = "ts_seconds")]
- pub expires_at: DateTime<Utc>,
- pub refresh_token: String,
- pub access_token: String,
- pub athlete: AthleteSummary,
+ if !status.is_success() {
+ return Err(From::from(error::StravaApiError::new(status, json)));
+ }
+ from_value(json).map_err(From::from)
+ }
}
pub fn exchange_token(client_id: &str, client_secret: &str, code: &str) -> Result<Token, Error> {