diff --git a/Cargo.toml b/Cargo.toml index fd88d14..74aef22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,19 @@ path = "src/lib.rs" #actix = ["tribufu-actix"] [dependencies] -tribufu-api = { version = "0.1.0", path = "./src/api" } +#tribufu-actix = { version = "0.1.0", path = "./src/actix", optional = true } +alnilam-consts = { version = "0.0.4" } +anyhow = "1.0.75" +base64 = "0.21.5" +chrono = { version = "0.4.22", features = ["serde", "rustc-serialize"] } +derive_more = "0.99.17" +mintaka-error = { version = "0.0.1" } +reqwest = { version = "0.11.18", features = ["json", "stream"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", features = ["raw_value"] } +serde_with = "3.4.0" tribufu-constants = { version = "0.1.0", path = "./src/constants" } tribufu-types = { version = "0.1.0", path = "./src/types" } -#tribufu-actix = { version = "0.1.0", path = "./src/actix", optional = true } [dev-dependencies] dotenv = "0.15.0" diff --git a/src/actix/Cargo.toml b/src/actix/Cargo.toml index fde32a0..f9fdc88 100644 --- a/src/actix/Cargo.toml +++ b/src/actix/Cargo.toml @@ -14,6 +14,6 @@ crate-type = ["rlib"] path = "lib.rs" [dependencies] +#tribufu-api = { path = "../api" } actix-web = { version = "4", features = ["rustls"] } mintaka-error = { version = "0.0.1" } -tribufu-api = { path = "../api" } diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..a87f9af --- /dev/null +++ b/src/api.rs @@ -0,0 +1,118 @@ +// Copyright (c) Tribufu. All Rights Reserved. + +use std::env; + +use reqwest::{ + header::{HeaderMap, HeaderValue, AUTHORIZATION}, + Client as HttpClient, +}; +use tribufu_constants::{TRIBUFU_API_URL, TRIBUFU_VERSION}; + +#[derive(Debug, Default)] +pub enum TribufuApiOptions { + #[default] + Anonymous, + ApiKey { + api_key: String, + }, + Token { + access_token: String, + refresh_token: Option, + expires_in: Option, + }, +} + +/// **Tribufu API** +/// +/// Use this class to interact with the Tribufu API. +/// +/// *There are three ways to use the Tribufu API:* +/// - A api key give you public read only access to the Tribufu API. +/// - A bot give you read and write access to the Tribufu API as a bot account. +/// - A client give you read and write access to the Tribufu API as a client application. +pub struct TribufuApi { + pub(crate) http: HttpClient, + pub(crate) options: TribufuApiOptions, +} + +impl Default for TribufuApi { + fn default() -> Self { + Self::new(TribufuApiOptions::Anonymous) + } +} + +impl TribufuApi { + pub fn new(options: TribufuApiOptions) -> Self { + let http = HttpClient::builder() + .default_headers(Self::default_headers()) + .build() + .unwrap(); + + TribufuApi { http, options } + } + + pub fn with_api_key(api_key: String) -> Self { + Self::new(TribufuApiOptions::ApiKey { api_key }) + } + + pub fn from_env(prefix: Option<&str>) -> Option { + let prefix = if let Some(prefix) = prefix { + format!("{}_", prefix) + } else { + "".to_string() + }; + + if let Ok(api_key) = env::var(format!("{prefix}API_KEY")) { + Some(Self::with_api_key(api_key)) + } else { + None + } + } + + pub fn from_env_or_default(prefix: Option<&str>) -> Self { + Self::from_env(prefix).unwrap_or_default() + } + + pub(crate) fn debug_enabled() -> bool { + return cfg!(debug_assertions); + } + + #[inline] + pub(crate) fn get_base_url() -> String { + if Self::debug_enabled() { + return env::var("TRIBUFU_API_URL").unwrap_or(TRIBUFU_API_URL.to_string()); + } + + TRIBUFU_API_URL.to_string() + } + + #[inline] + fn default_headers() -> HeaderMap { + let mut headers = HeaderMap::new(); + headers.insert("X-Tribufu-Language", "rust".parse().unwrap()); + headers.insert("X-Tribufu-Version", TRIBUFU_VERSION.parse().unwrap()); + headers + } + + pub(crate) fn headers(&self) -> HeaderMap { + let mut headers = TribufuApi::default_headers(); + + match &self.options { + TribufuApiOptions::ApiKey { api_key } => { + headers.insert( + "Authorization", + HeaderValue::from_str(&format!("ApiKey {}", api_key)).unwrap(), + ); + } + TribufuApiOptions::Token { access_token, .. } => { + headers.insert( + "Authorization", + HeaderValue::from_str(&format!("Bearer {}", access_token)).unwrap(), + ); + } + _ => {} + } + + headers + } +} diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml deleted file mode 100644 index 9de8779..0000000 --- a/src/api/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "tribufu-api" -version = "0.1.0" -description = "Tribufu API" -repository = "https://github.com/Tribufu/TribufuRust" -authors = ["Tribufu "] -license = "MIT" -edition = "2021" -publish = true - -[lib] -name = "tribufu_api" -crate-type = ["rlib"] -path = "lib.rs" - -[dependencies] -tribufu-constants = { version = "0.1.0", path = "../constants" } -tribufu-types = { version = "0.1.0", path = "../types" } -base64 = "0.21.5" -mintaka-error = { version = "0.0.1" } -alnilam-consts = { version = "0.0.4" } -anyhow = "1.0.75" -chrono = { version = "0.4.22", features = ["serde", "rustc-serialize"] } -derive_more = "0.99.17" -reqwest = { version = "0.11.18", features = ["json", "stream"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = { version = "1.0", features = ["raw_value"] } -serde_with = "3.4.0" diff --git a/src/api/lib.rs b/src/api2.rs similarity index 96% rename from src/api/lib.rs rename to src/api2.rs index 19bfad6..7fa93b8 100644 --- a/src/api/lib.rs +++ b/src/api2.rs @@ -5,7 +5,7 @@ use mintaka_error::{Error, Result}; use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION}; use reqwest::Client; use std::env; -use tribufu_constants::VERSION; +use tribufu_constants::TRIBUFU_VERSION; use tribufu_types::games::Game; use tribufu_types::oauth2::{OAuth2GrantType, OAuth2TokenRequest, OAuth2TokenResponse}; use tribufu_types::users::*; @@ -35,16 +35,7 @@ pub enum Token { } pub struct TribufuApi { - base_url: String, - credentials: Credentials, - token: Option, - http: Client, -} -impl Default for TribufuApi { - fn default() -> Self { - Self::new(Credentials::Anonymous) - } } impl TribufuApi { @@ -73,7 +64,7 @@ impl TribufuApi { fn user_agent() -> String { format!( "Tribufu/{} (+https://api.tribufu.com; {})", - VERSION, TARGET_TRIPLE + TRIBUFU_VERSION, TARGET_TRIPLE ) } @@ -81,7 +72,10 @@ impl TribufuApi { fn default_headers() -> HeaderMap { let mut headers = HeaderMap::new(); headers.insert("X-Tribufu-Language", HeaderValue::from_static("rust")); - headers.insert("X-Tribufu-Version", HeaderValue::from_static(VERSION)); + headers.insert( + "X-Tribufu-Version", + HeaderValue::from_static(TRIBUFU_VERSION), + ); headers } diff --git a/src/bot.rs b/src/bot.rs new file mode 100644 index 0000000..143a08f --- /dev/null +++ b/src/bot.rs @@ -0,0 +1 @@ +// Copyright (c) Tribufu. All Rights Reserved. diff --git a/src/client.rs b/src/client.rs new file mode 100644 index 0000000..1264b76 --- /dev/null +++ b/src/client.rs @@ -0,0 +1,83 @@ +// Copyright (c) Tribufu. All Rights Reserved. + +use std::env; + +use reqwest::header::{HeaderMap, HeaderValue}; + +use crate::{TribufuApi, TribufuApiOptions}; + +pub struct TribufuClient { + client_id: u64, + client_secret: String, + api: TribufuApi, +} + +impl TribufuClient { + pub fn new(client_id: u64, client_secret: impl Into) -> Self { + Self { + client_id, + client_secret: client_secret.into(), + api: TribufuApi::default(), + } + } + + pub fn from_env(prefix: Option<&str>) -> Option { + let prefix = if let Some(prefix) = prefix { + format!("{}_", prefix) + } else { + "".to_string() + }; + + let client_id = env::var(format!("{prefix}CLIENT_ID")); + let client_secret = env::var(format!("{prefix}CLIENT_SECRET")); + + if let (Ok(client_id), Ok(client_secret)) = (client_id, client_secret) { + Some(Self::new(client_id.parse().unwrap(), client_secret)) + } else { + None + } + } + + pub(crate) fn set_tokens( + &mut self, + access_token: String, + refresh_token: Option, + expires_in: Option, + ) { + self.api.options = TribufuApiOptions::Token { + access_token, + refresh_token, + expires_in, + }; + } + + pub(crate) fn clear_tokens(&mut self) { + self.api.options = TribufuApiOptions::Anonymous; + } + + #[inline] + fn oauth_headers(&self) -> HeaderMap { + let mut headers = self.api.headers(); + + headers.insert("Authorization", HeaderValue::from_str("Basic").unwrap()); + + headers.insert( + "Content-Type", + HeaderValue::from_str("application/x-www-form-urlencoded").unwrap(), + ); + + headers + } + + pub fn api(&self) -> &TribufuApi { + &self.api + } + + pub fn api_mut(&mut self) -> &mut TribufuApi { + &mut self.api + } + + pub fn client_id(&self) -> u64 { + self.client_id + } +} diff --git a/src/constants/lib.rs b/src/constants/lib.rs index e0fcb7e..2315f34 100644 --- a/src/constants/lib.rs +++ b/src/constants/lib.rs @@ -1,3 +1,13 @@ // Copyright (c) Tribufu. All Rights Reserved. -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +/// The version of the Tribufu SDK. +pub const TRIBUFU_VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +/// The default Tribufu API URL. +pub const TRIBUFU_API_URL: &'static str = "https://api.tribufu.com"; + +/// The default Tribufu WEB URL. +pub const TRIBUFU_WEB_URL: &'static str = "https://www.tribufu.com"; + +/// The default Tribufu CDN URL. +pub const TRIBUFU_CDN_URL: &'static str = "https://cdn.tribufu.com"; diff --git a/src/lib.rs b/src/lib.rs index d5ea72e..76f24d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,17 @@ // Copyright (c) Tribufu. All Rights Reserved. -pub use tribufu_api::*; -pub use tribufu_constants::VERSION; +#![allow(dead_code)] +#![allow(unused_imports)] + +pub use tribufu_constants::TRIBUFU_VERSION; pub use tribufu_types as types; + +mod api; +mod bot; +mod client; +mod server; + +pub use api::*; +pub use bot::*; +pub use client::*; +pub use server::*; diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..9577948 --- /dev/null +++ b/src/server.rs @@ -0,0 +1,37 @@ +// Copyright (c) Tribufu. All Rights Reserved. + +use crate::{TribufuApi, TribufuClient}; + +pub struct TribufuServer { + server_id: u64, + client: TribufuClient, +} + +impl TribufuServer { + pub fn new(server_id: u64, client_id: u64, client_secret: impl Into) -> Self { + Self { + server_id, + client: TribufuClient::new(client_id, client_secret), + } + } + + pub fn api(&self) -> &TribufuApi { + self.client.api() + } + + pub fn api_mut(&mut self) -> &mut TribufuApi { + self.client.api_mut() + } + + pub fn client(&self) -> &TribufuClient { + &self.client + } + + pub fn client_mut(&mut self) -> &mut TribufuClient { + &mut self.client + } + + pub fn server_id(&self) -> u64 { + self.server_id + } +}