froxy/froxy-scraper/src/state.rs
2026-02-06 23:24:21 +01:00

138 lines
3.4 KiB
Rust

use std::borrow::Cow;
use reqwest::{Method, Response};
use secrecy::{ExposeSecret, SecretString};
use url::UrlQuery;
macro_rules! const_from_env {
($const:ident, $env:literal) => {
const $const: Option<&'static str> = option_env!($env);
};
($const:ident, $env:literal, $default:expr) => {
const $const: &'static str = match option_env!($env) {
Some(s) => s,
None => $default,
};
};
}
const_from_env!(USER_AGENT_APP, "FROXY_UA_APP_NAME", "Froxy");
const_from_env!(USER_AGENT_VERSION, "FROXY_UA_APP_VERSION", {
const_from_env!(CARGO_PKG_VERSION, "CARGO_PKG_VERSION", "0.1-alpha");
CARGO_PKG_VERSION
});
const_from_env!(
USER_AGENT_DESC,
"FROXY_UA_DESC",
"(by maiboyer; for maiboyer)"
);
pub const DEFAULT_USER_AGENT: &str =
constcat::concat!(USER_AGENT_APP, "/", USER_AGENT_VERSION, USER_AGENT_DESC);
#[derive(Debug, Clone)]
pub struct State {
client: reqwest::Client,
base_url: url::Url,
secret_cookie: secrecy::SecretString,
user_agent: std::borrow::Cow<'static, str>,
}
impl State {
pub fn new(secret_cookie: impl AsRef<str>) -> Self {
let user_agent = DEFAULT_USER_AGENT;
let base_url = "https://friends.42paris.fr";
Self::with_info(
secret_cookie,
user_agent.into(),
url::Url::parse(base_url).expect("default base url not valid"),
)
}
pub fn with_info(
secret_cookie: impl AsRef<str>,
user_agent: std::borrow::Cow<'static, str>,
base_url: url::Url,
) -> Self {
let client = reqwest::Client::builder()
.user_agent(&*user_agent)
.build()
.unwrap();
Self {
client,
base_url,
secret_cookie: secret_cookie.as_ref().into(),
user_agent,
}
}
pub fn client(&self) -> &reqwest::Client {
&self.client
}
pub fn base_url(&self) -> &url::Url {
&self.base_url
}
pub fn cookie(&self) -> &SecretString {
&self.secret_cookie
}
pub fn user_agent(&self) -> &str {
&self.user_agent
}
}
impl State {
pub async fn request(
&self,
method: Method,
url: impl AsRef<str>,
qs: Option<&str>,
body: Option<Vec<u8>>,
) -> Result<Response, reqwest::Error> {
let mut u = self.base_url.clone();
u.set_path(url.as_ref());
u.set_query(qs);
let builder = self
.client
.request(method, u)
.header("Cookie", self.secret_cookie.expose_secret());
let builder = if let Some(body) = body {
builder.body(body)
} else {
builder
};
builder.send().await
}
pub async fn get(
&self,
url: impl AsRef<str>,
qs: Option<&str>,
) -> Result<Response, reqwest::Error> {
self.request(Method::GET, url.as_ref(), qs, None).await
}
pub async fn post(
&self,
url: impl AsRef<str>,
qs: Option<&str>,
) -> Result<Response, reqwest::Error> {
self.request(Method::POST, url.as_ref(), qs, None).await
}
pub async fn post_with_body(
&self,
url: impl AsRef<str>,
qs: Option<&str>,
body: Vec<u8>,
) -> Result<Response, reqwest::Error> {
self.request(Method::POST, url.as_ref(), qs, Some(body))
.await
}
}