receipts/src/firefly.rs

87 lines
2.1 KiB
Rust

use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::Client;
use serde::Deserialize;
pub struct Firefly {
url: String,
client: reqwest::Client,
}
#[derive(Deserialize)]
pub struct TransactionSplit {
pub date: chrono::DateTime<chrono::FixedOffset>,
pub amount: String,
pub description: String,
}
#[derive(Deserialize)]
pub struct TransactionAttributes {
pub group_title: Option<String>,
pub transactions: Vec<TransactionSplit>,
}
#[derive(Deserialize)]
pub struct TransactionRead {
pub id: String,
pub attributes: TransactionAttributes,
}
#[derive(Deserialize)]
pub struct TransactionArray {
pub data: Vec<TransactionRead>,
}
#[derive(Deserialize)]
pub struct TransactionSingle {
pub data: TransactionRead,
}
impl Firefly {
pub fn new(url: impl Into<String>, token: &str) -> Self {
let mut headers = HeaderMap::new();
headers.insert(
"Accept",
HeaderValue::from_static("application/vnd.api+json"),
);
headers.insert(
"Authorization",
HeaderValue::from_str(&format!("Bearer {}", &token)).unwrap(),
);
let client =
Client::builder().default_headers(headers).build().unwrap();
Self {
url: url.into().trim_end_matches("/").into(),
client,
}
}
pub fn url(&self) -> &str {
&self.url
}
pub async fn search_transactions(
&self,
query: &str,
) -> Result<TransactionArray, reqwest::Error> {
let url = format!("{}/api/v1/search/transactions", self.url);
let res = self
.client
.get(url)
.query(&[("query", query)])
.send()
.await?;
res.error_for_status_ref()?;
res.json().await
}
pub async fn get_transaction(
&self,
id: &str,
) -> Result<TransactionSingle, reqwest::Error> {
let url = format!("{}/api/v1/transactions/{}", self.url, id);
let res = self.client.get(url).send().await?;
res.error_for_status_ref()?;
res.json().await
}
}