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}