use serde::{Deserialize, Serialize};
use std::fmt;
pub const DEFAULT_PLATFORM_URL: &str = "https://leash.build";
#[derive(Debug)]
pub enum LeashError {
NotConnected {
message: String,
connect_url: Option<String>,
},
TokenExpired { message: String },
ApiError {
message: String,
code: Option<String>,
},
NetworkError(reqwest::Error),
}
impl fmt::Display for LeashError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LeashError::NotConnected { message, .. } => write!(f, "leash: not connected: {message}"),
LeashError::TokenExpired { message } => write!(f, "leash: token expired: {message}"),
LeashError::ApiError { message, code } => {
if let Some(c) = code {
write!(f, "leash: {message} (code: {c})")
} else {
write!(f, "leash: {message}")
}
}
LeashError::NetworkError(e) => write!(f, "leash: network error: {e}"),
}
}
}
impl std::error::Error for LeashError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
LeashError::NetworkError(e) => Some(e),
_ => None,
}
}
}
impl From<reqwest::Error> for LeashError {
fn from(err: reqwest::Error) -> Self {
LeashError::NetworkError(err)
}
}
#[derive(Debug, Deserialize)]
pub(crate) struct ApiResponse {
pub success: bool,
pub data: Option<serde_json::Value>,
pub error: Option<String>,
pub code: Option<String>,
#[serde(rename = "connectUrl")]
pub connect_url: Option<String>,
}
impl ApiResponse {
pub fn into_error(self) -> LeashError {
let message = self.error.unwrap_or_else(|| "unknown error".to_string());
let code = self.code;
match code.as_deref() {
Some("not_connected") => LeashError::NotConnected {
message,
connect_url: self.connect_url,
},
Some("token_expired") => LeashError::TokenExpired { message },
_ => LeashError::ApiError { message, code },
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionStatus {
#[serde(rename = "providerId")]
pub provider_id: String,
pub status: String,
#[serde(default)]
pub email: Option<String>,
#[serde(default, rename = "expiresAt")]
pub expires_at: Option<String>,
}
#[derive(Debug, Default, Clone, Serialize)]
pub struct ListMessagesParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "maxResults")]
pub max_results: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "labelIds")]
pub label_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none", rename = "pageToken")]
pub page_token: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct SendMessageParams {
pub to: String,
pub subject: String,
pub body: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<String>,
}
#[derive(Debug, Default, Clone, Serialize)]
pub struct ListEventsParams {
#[serde(skip_serializing_if = "Option::is_none", rename = "calendarId")]
pub calendar_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "timeMin")]
pub time_min: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "timeMax")]
pub time_max: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "maxResults")]
pub max_results: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "singleEvents")]
pub single_events: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none", rename = "orderBy")]
pub order_by: Option<String>,
}
#[derive(Debug, Default, Clone, Serialize)]
pub struct EventDateTime {
#[serde(skip_serializing_if = "Option::is_none", rename = "dateTime")]
pub date_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "timeZone")]
pub time_zone: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct Attendee {
pub email: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct CreateEventParams {
#[serde(skip_serializing_if = "Option::is_none", rename = "calendarId")]
pub calendar_id: Option<String>,
pub summary: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<String>,
pub start: EventDateTime,
pub end: EventDateTime,
#[serde(skip_serializing_if = "Option::is_none")]
pub attendees: Option<Vec<Attendee>>,
}
#[derive(Debug, Default, Clone, Serialize)]
pub struct ListFilesParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", rename = "maxResults")]
pub max_results: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "folderId")]
pub folder_id: Option<String>,
}