ccash_rs/
lib.rs

1#![warn(missing_docs, clippy::pedantic)]
2#![allow(clippy::module_name_repetitions)]
3#![doc = include_str!("../README.md")]
4
5#[macro_use]
6mod request;
7pub mod methods;
8pub mod responses;
9pub mod user;
10
11pub use crate::{responses::*, user::*};
12use chrono::prelude::*;
13use reqwest::Client;
14use serde::Deserialize;
15use std::fmt;
16
17/// Struct that decribes the properties of the `CCash` instance that are
18/// returned from the `properties` endpoint. Helps define the behaviour of this
19/// API.
20#[derive(Clone, Debug, Deserialize)]
21pub struct CCashSessionProperties {
22    /// Returns the version of the `CCash` instance.
23    pub version: u32,
24    /// The max amount of logs that can be returned by the `CCash` instance.
25    pub max_log: u32,
26    /// The account that funds are returned to when an account with funds is
27    /// deleted from the `CCash` instance. This field is optional as this is
28    /// an option chosen by the host to include at compile-time, and may not
29    /// always be present in the API properties returned by `CCash` on all
30    /// instances.
31    pub return_on_del: Option<String>,
32}
33
34/// Struct that describes the format of the logs returned by
35/// [`get_logs`](`methods::get_logs`).
36#[derive(Debug, Deserialize)]
37pub struct TransactionLog {
38    /// The account to which the funds were sent to.
39    pub to: String,
40    /// The account from which the funds were sent from.
41    pub from: String,
42    /// The amount of CSH that was sent.
43    pub amount: u32,
44    /// The time that the funds were sent in Unix epoch time.
45    pub time: i64,
46}
47
48impl fmt::Display for TransactionLog {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        write!(
51            f,
52            "{}: {} ({} CSH) -> {}",
53            DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.time, 0), Utc),
54            &self.from,
55            self.amount,
56            &self.to,
57        )
58    }
59}
60
61/// Struct that describes the connection to the `CCash` API instance which is
62/// defined by the `session_url`.
63///
64/// # Usage
65/// The intended usage for this struct is to provide a simple way to connect to
66/// the `CCash` instance and be passed into the functions provided by
67/// [`methods`] and [`methods::admin`]. This also means multiple `CCashSession`s
68/// can be connected to different `CCash` instances, if need be.
69///
70/// An example usage is as follows
71/// (available [here](https://git.stboyden.com/STBoyden/ccash-rs/src/branch/master/examples/get_balance.rs)):
72/// ```
73#[doc = include_str!("../examples/get_balance.rs")]
74/// }
75/// ```
76/// 
77/// Before any function from [`methods`] and [`methods::admin`] is called,
78/// [`establish_connection`](CCashSession::establish_connection) must be called
79/// to make sure that the connection to the `CCash` instance is secured and
80/// correct. This also makes sure that the properties of `CCashSession` is
81/// properly set and not `None`.
82#[derive(Debug, Clone)]
83pub struct CCashSession {
84    session_url: String,
85    is_connected: bool,
86    client: Option<Client>,
87    properties: Option<CCashSessionProperties>,
88}
89
90impl CCashSession {
91    /// Constructs a new `CCashSession` from a `base_url`
92    #[must_use]
93    pub fn new(base_url: &str) -> CCashSession {
94        Self {
95            session_url: format!("{}/api", base_url),
96            is_connected: false,
97            client: None,
98            properties: None,
99        }
100    }
101
102    /// Establishes a connection to the `CCash` instance using the
103    /// `session_url`.
104    ///
105    /// # Errors
106    ///
107    /// Will return `CCashError::CouldNotParsePropertiesResponse` if the
108    /// properties returned by `CCash` could not be parsed correctly.
109    pub async fn establish_connection(&mut self) -> Result<(), CCashError> {
110        if self.is_connected {
111            return Ok(());
112        }
113
114        let client = Client::builder().build()?;
115
116        let request = client
117            .get(format!("{}/properties", self.session_url))
118            .header("Accept", "application/json")
119            .build()?;
120
121        let response = client.execute(request).await?;
122
123        if let Ok(v) = response.json::<CCashSessionProperties>().await {
124            self.properties = Some(v.clone());
125            self.session_url = format!("{}/v{}", self.session_url, v.version);
126
127            self.is_connected = true;
128            self.client = Some(client);
129            Ok(())
130        } else {
131            Err(CCashError::CouldNotParsePropertiesResponse)
132        }
133    }
134
135    /// Gets the client associated with this instance of `CCashSession`
136    #[must_use]
137    pub fn get_client(&self) -> &Option<Client> { &self.client }
138    /// Returns whether or not the `CCashSession` is connectd to the instance.
139    #[must_use]
140    pub fn is_connected(&self) -> bool { self.is_connected }
141    /// Returns the properties of the `CCash` instance.
142    #[must_use]
143    pub fn get_properties(&self) -> &Option<CCashSessionProperties> { &self.properties }
144}