add type definition, basic request building

This commit is contained in:
YK 2025-04-12 22:05:46 +03:00
parent 5b911e216d
commit b59f18e358
4 changed files with 214 additions and 2 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
/target
cookie.txt
.env

43
Cargo.lock generated
View File

@ -8,6 +8,12 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "anyhow"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]]
name = "base64"
version = "0.22.1"
@ -35,6 +41,26 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "const_format"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "cookie"
version = "0.18.1"
@ -102,6 +128,12 @@ dependencies = [
"litrs",
]
[[package]]
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "encoding_rs"
version = "0.8.35"
@ -477,6 +509,11 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
name = "semargl"
version = "0.1.0"
dependencies = [
"anyhow",
"const_format",
"dotenvy",
"serde",
"serde_json",
"ureq",
]
@ -605,6 +642,12 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
version = "0.9.0"

View File

@ -4,4 +4,9 @@ version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.97"
const_format = "0.2.34"
dotenvy = "0.15.7"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
ureq = { version = "3.0.10", features = ["charset", "cookies", "json"] }

View File

@ -1,3 +1,165 @@
fn main() {
println!("Hello, world!");
#![allow(non_upper_case_globals)]
use std::{ env, error::Error, fs::File, io::Read, sync::LazyLock, time::Duration };
use anyhow::Result;
use const_format::formatcp;
use serde::{ Serialize, Deserialize };
use ureq::{ http::Response, Agent, Body };
const MAX_USERS_PER_PAGE: u8 = 50;
const cookie_filename: &'static str = "cookie.txt";
const host: &'static str = "members.tilda.ru";
const project_id: u32 = 11795571;
const origin: &'static str = formatcp!("https://{host}");
const referer: &'static str = formatcp!("{origin}/{project_id}/");
const endpoint: &'static str = formatcp!("{origin}/api/getmembers/");
const user_agent: &'static str = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36";
#[derive(Debug, Clone, Deserialize, Serialize)]
enum RequestSort {
#[serde(rename = "nameAsc")]
NameAsc
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Request {
pub page: u16,
pub page_size: u8,
pub sort: RequestSort,
pub project_id: u32,
}
impl Default for Request {
fn default () -> Self {
Self { page: 1, page_size: MAX_USERS_PER_PAGE, sort: RequestSort::NameAsc, project_id }
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
enum Resp {
Ok (OkResp),
Err (ErrResp),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct OkResp {
pub status: String,
pub data: ResponseData
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct ErrResp {
pub status: String,
pub code: String
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct ResponseData {
pub total: u32,
pub total_active: u32,
pub pages: u32,
pub members: Vec<Member>,
pub page: u32,
pub page_size: u32,
pub login_url: String,
#[serde(rename = "singUpUrl")] // [sic]
pub sign_up_url: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Member {
pub id: u32,
pub name: String,
pub login: String,
pub added_date: String,
pub activity: bool,
pub avatar: Option<String>,
pub last_online_date: String,
pub groups: Vec<Group>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Group {
pub id: u32,
pub name: String
}
impl Request {
fn for_page (page: u16) -> Self {
let mut _self = Self::default();
_self.page = page;
_self
}
fn send (&self, cookie: &str) -> Result<Response<Body>> {
let agent: Agent = Agent::config_builder()
.timeout_global(Some(Duration::from_secs(5)))
.user_agent(user_agent)
.build()
.into();
let builder = agent.post(endpoint)
.content_type("text/plain;charset=UTF-8")
.header("Host", host)
.header("Origin", origin)
.header("Referer", referer)
.header("Cookie", cookie);
let body = serde_json::to_string(self)?;
Ok(builder.send(body)?)
}
}
/// @TODO
fn try_get_cookie () -> Result<()> {
Ok(())
}
fn read_cookie (filename: &str) -> Option<String> {
let mut cookie_file = File::open(filename).ok()?;
let mut cookie = String::new();
cookie_file.read_to_string(&mut cookie).ok()?;
cookie = cookie.trim().to_owned();
if cookie.is_empty() { return None; }
Some(cookie)
}
fn retrieve_users (cookie: &str) {
}
fn main () {
let cookie = read_cookie(cookie_filename).expect(&format!("Directory with executable should contain `{cookie_filename}` file containing a valid cookie for accessing Tilda control panel"));
let req = Request::default().send(&cookie);
if let Ok(mut req) = req {
let mut body = req.body_mut();
println!("{:?}", body.read_json::<Resp>());
}
// println!("{} {} {} {} {} {}", host, project_id, &*origin, &*referer, user_agent, cookie);
}