Skip to content

Commit

Permalink
v0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Mon-ius committed Aug 11, 2024
1 parent 4ec924c commit c42731c
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: weekly
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: ci

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_TERM_COLOR: always
CARGO_LOCA: "Cargo.toml"
CARGO_BIN: "aw"

permissions:
contents: write

on:
workflow_dispatch:
push:
branches:
- "master"
paths:
- "Cargo.toml"
- ".github/workflows/ci.yml"

jobs:
pre:
runs-on: ubuntu-latest
outputs:
cargo_loc: ${{ env.CARGO_LOCA }}
cargo_bin: ${{ env.CARGO_BIN }}
steps:
- run: echo "Bypass GitHub Action Restriction"

call:
needs:
- pre
uses: AUTOM77/Rust-Actions/.github/workflows/ci.yml@main
with:
cargo_loc: ${{ needs.pre.outputs.cargo_loc }}
cargo_bin: ${{ needs.pre.outputs.cargo_bin }}
secrets: inherit
30 changes: 30 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "aw"
version = "0.0.1"
edition = "2021"

[dependencies]
clap = { version = "4.5.15", features = ["derive"] }
tokio = { version = "1.39.2", default-features = false, features = ["rt", "sync"] }
reqwest = { version = "0.12.5", default-features = false, features = ["http2", "json", "rustls-tls"] }
serde_json = { version = "1.0.120", default-features = false, features = ["alloc"] }
serde = { version = "1.0.204", features = ["derive"] }
ring = { version = "0.17.8", default-features = false}
tokio-stream = "0.1.15"
chrono = "0.4.38"
base64 = "0.22.1"

[[bin]]
name = "aw"
path = "src/cli.rs"

[lib]
name = "ld_"
path = "src/lib.rs"

[profile.release]
lto = false
strip = true
panic = 'abort'
opt-level = 3
codegen-units = 1
14 changes: 14 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use clap::Parser;

#[derive(Parser)]
struct Cli {
n: usize,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
let start_time = std::time::Instant::now();
let cli = Cli::parse();
let _ = ld_::interface(cli.n);
println!("Processing time: {:?}", start_time.elapsed());
Ok(())
}
12 changes: 12 additions & 0 deletions src/client/cipher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use ring::{agreement, rand};
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};

pub fn get_key() -> String {
let rng = rand::SystemRandom::new();
let private_key = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap();
let public_key = private_key.compute_public_key().unwrap();

let res = BASE64.encode(&public_key);
res
}

11 changes: 11 additions & 0 deletions src/client/date.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use chrono::{DateTime, FixedOffset, Local, SecondsFormat};

pub fn get_tos() -> String {
let local_time: DateTime<Local> = Local::now();
let offset = FixedOffset::west_opt(2 * 3600).expect("Invalid offset");
let date_time = local_time.with_timezone(&offset);
let formatted = date_time.to_rfc3339_opts(SecondsFormat::Millis, true);

formatted
}

5 changes: 5 additions & 0 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod warp;
pub use warp::WARP;

pub mod date;
pub mod cipher;
125 changes: 125 additions & 0 deletions src/client/warp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use serde_json::json;
use serde::{Deserialize, Serialize};
use tokio::time::{sleep, Duration};

use super::cipher;
use super::date;

const END_POINT: &str = "https://api.cloudflareclient.com/v0a2077/reg";
const RETRY_DELAY: Duration = Duration::from_secs(60);

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ACCOUNT {
pub id: String,
pub license: String
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WARP {
pub id: String,
pub key: String,
pub token: String,
pub account: ACCOUNT
}

impl WARP {
pub async fn new() -> Result<Self, Box<dyn std::error::Error>>{
let payload = json!({
"tos": date::get_tos(),
"key": cipher::get_key()
});

let client = reqwest::Client::builder()
.http2_keep_alive_timeout(std::time::Duration::from_secs(15))
.build()?;

let response = client.post(END_POINT)
.json(&payload)
.send()
.await?;

if !response.status().is_success() {
return Err(format!("HTTP error: {}", response.text().await?).into());
}

let warp = response
.json::<WARP>()
.await?;
Ok(warp)
}

pub async fn build() -> Result<Self, Box<dyn std::error::Error>>{
let warp = loop {
match Self::new().await {
Ok(warp) => break warp,
Err(_) => {
eprintln!("Retrying in {} seconds...", RETRY_DELAY.as_secs());
sleep(RETRY_DELAY).await;
},
}
};

Ok(warp)
}

pub async fn update(&mut self, license: String) -> Result<String, Box<dyn std::error::Error>>{
let end_point = format!("{}/{}/account", END_POINT, self.id);
let payload = json!({
"license": license,
});

let client = reqwest::Client::builder()
.http2_keep_alive_timeout(std::time::Duration::from_secs(15))
.build()?;

let response = client.put(end_point.clone())
.bearer_auth(&self.token)
.json(&payload)
.send()
.await?;

if !response.status().is_success() {
return Err(format!("PUT HTTP error: {}", response.text().await?).into());
}

let response = client.get(end_point)
.bearer_auth(&self.token)
.send()
.await?;

if !response.status().is_success() {
return Err(format!("GET HTTP error: {}", response.text().await?).into());
}

let last_license = self.account.license.clone();
self.account = response.json::<ACCOUNT>().await?;
Ok(last_license)
}

pub async fn delete(&self) -> Result<(), Box<dyn std::error::Error>>{
let end_point = format!("{}/{}", END_POINT, self.id);

let client = reqwest::Client::builder()
.http2_keep_alive_timeout(std::time::Duration::from_secs(45))
.build()?;

let response = client.delete(end_point)
.bearer_auth(&self.token)
.send()
.await?;

if !response.status().is_success() {
return Err(format!("DELETE HTTP error: {}", response.text().await?).into());
}
Ok(())
}

pub async fn get_license(&mut self, seed: String) -> Result<String, Box<dyn std::error::Error>>{
let license = self.update(seed).await.unwrap();
let seed = self.update(license.clone()).await.unwrap();
let _ = self.delete().await.unwrap();

Ok(license)
}

}
42 changes: 42 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use tokio_stream::{StreamExt, iter};
pub mod client;

const CAPACITY: usize = 5;
const SEED: &str ="0U7h98No-L6987BhV-uDd80i36";

pub async fn run_tokio(num: usize) -> Result<(), Box<dyn std::error::Error>> {
let semaphore = std::sync::Arc::new(tokio::sync::Semaphore::new(CAPACITY));

let tasks: Vec<_> = iter(0..num)
.map(|_| {
let semaphore = semaphore.clone();
async move {
let permit = semaphore.acquire_owned().await.unwrap();
let license = match client::WARP::build().await {
Ok(mut a) => a.get_license(SEED.into()).await.unwrap(),
Err(_) => format!("error"),
};

println!("{:#?}", license);
drop(permit);
}
})
.collect().await;

for task in tasks {
task.await;
}

Ok(())
}

pub fn interface(num: usize) -> Result<(), Box<dyn std::error::Error>> {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();

println!("Processing num: {:?}", num);
let _ = rt.block_on(run_tokio(num));
Ok(())
}

0 comments on commit c42731c

Please sign in to comment.