maxbot 0.1.2

Автоматизация работы с чат-ботами MAX
Documentation
// examples/stress_test.rs
// Стресс-тест ограничения RPS: отправляет сообщения на максимальной скорости до первой ошибки 429.
//
// Использование: cargo run --example stress_test -- <bot_token> <chat_id> <rps>
//   rps - желаемое количество запросов в секунду (целое число, >0).
//
// Пример: cargo run --example stress_test -- "ваш_токен" 123456789 50

use maxbot_rs::{MaxClient, SendMessageParamsBuilder, set_global_max_rps, set_global_base_url};
use std::time::{Duration, Instant};
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = env::args().collect();
    if args.len() < 4 {
        eprintln!("Usage: {} <bot_token> <chat_id> <rps>", args[0]);
        std::process::exit(1);
    }
    let token = &args[1];
    let chat_id: i64 = args[2].parse()?;
    let rps: usize = args[3].parse()?;
    if rps == 0 {
        eprintln!("RPS must be positive.");
        std::process::exit(1);
    }

    // Если задан прокси через переменную окружения MAXBOT_PROXY, используем его
    if let Ok(proxy_url) = env::var("MAXBOT_PROXY") {
        println!("Using proxy base URL: {}", proxy_url);
        set_global_base_url(proxy_url);
    }

    // Устанавливаем глобальное ограничение RPS для библиотеки
    set_global_max_rps(rps);
    println!("Starting stress test with {} requests per second.", rps);
    println!("Sending messages to chat {}...", chat_id);

    let client = MaxClient::new(token);
    let interval = Duration::from_millis(1000 / rps as u64);
    let mut msg_counter = 0;
    let start_time = Instant::now();

    loop {
        msg_counter += 1;
        let text = format!("Stress test message #{}", msg_counter);
        let builder = SendMessageParamsBuilder::new()
            .text(text)
            .chat_id(chat_id)
            .silent(true);      // не беспокоим пользователей

        let before = Instant::now();
        let result = client.send_message_builder(builder).await;
        let elapsed = before.elapsed();

        match result {
            Ok(ids) => {
                let mid = ids.first().unwrap();
                print!("\rSent #{} (mid={}, took {} ms)", msg_counter, mid, elapsed.as_millis());
                // Небольшая пауза, чтобы не перегружать CPU – библиотека уже обеспечит задержку,
                // но для равномерности можно сделать паузу.
                tokio::time::sleep(interval).await;
            }
            Err(e) => {
                let err_str = e.to_string();
                if err_str.contains("429") || err_str.contains("too.many.requests") {
                    let total_sec = start_time.elapsed().as_secs_f64();
                    let successful = msg_counter - 1;
                    println!("\n\nRate limit hit after {} successful messages.", successful);
                    println!("Error: {}", err_str);
                    println!("Test finished. Sent {} messages in {:.2} seconds (avg {:.2} msg/sec).",
                             successful, total_sec, successful as f64 / total_sec);
                    return Ok(());
                } else {
                    eprintln!("\nUnexpected error: {}", err_str);
                    return Err(e);
                }
            }
        }
    }
}