niazpardaz-sms 1.0.3

Official Rust SDK for Niazpardaz SMS API | کتابخانه رسمی Rust برای API پیامکی نیازپرداز
Documentation

Niazpardaz SMS SDK for Rust

Official Rust SDK for Niazpardaz SMS API | کتابخانه رسمی Rust برای API پیامکی نیازپرداز

Crates.io Tests License

Features | امکانات

  • Async & Blocking — هم async با tokio و هم blocking (سنکرون)
  • Rust 1.75+ — حداقل نسخه پشتیبانی
  • Builder Pattern — ساخت کلاینت با تنظیمات سفارشی
  • Type-safe — تمام کدهای نتیجه با newtype pattern و description فارسی
  • Error handling — خطاهای strongly typed با thiserror
  • TLS — پشتیبانی از rustls (بدون نیاز به OpenSSL)
  • Thread-safeSend + Sync برای استفاده در چند thread

نصب | Installation

[dependencies]
niazpardaz-sms = "1.0"
tokio = { version = "1", features = ["full"] }

برای نسخه blocking (بدون async):

[dependencies]
niazpardaz-sms = { version = "1.0", features = ["blocking"] }

شروع سریع | Quick Start

Async (پیش‌فرض)

use niazpardaz_sms::NiazpardazClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = NiazpardazClient::new("YOUR_API_KEY");

    let result = client.send("10001234", "09123456789", "سلام از نیازپرداز!").await?;

    if result.is_successful() {
        println!("BatchSmsId: {}", result.batch_sms_id);
    } else {
        println!("Error: {}", result.result_code.description());
    }

    Ok(())
}

Blocking (سنکرون)

use niazpardaz_sms::BlockingClient;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = BlockingClient::new("YOUR_API_KEY");

    let result = client.send("10001234", "09123456789", "سلام!")?;
    println!("BatchSmsId: {}", result.batch_sms_id);

    Ok(())
}

تنظیمات | Configuration

use niazpardaz_sms::NiazpardazClient;
use std::time::Duration;

// با Builder Pattern
let client = NiazpardazClient::builder("YOUR_API_KEY")
    .timeout(Duration::from_secs(60))
    .base_url("https://custom.api.com")
    .build();

// با HTTP Client سفارشی (مثلاً با پروکسی)
let http_client = reqwest::Client::builder()
    .timeout(Duration::from_secs(30))
    .proxy(reqwest::Proxy::all("http://proxy:8080")?)
    .build()?;

let client = NiazpardazClient::builder("YOUR_API_KEY")
    .http_client(http_client)
    .build();

استفاده در فریم‌ورک‌ها | Framework Integration

Actix Web

use actix_web::{web, App, HttpServer, HttpResponse};
use niazpardaz_sms::NiazpardazClient;
use std::sync::Arc;

struct AppState {
    sms_client: NiazpardazClient,
}

async fn send_sms(
    data: web::Data<Arc<AppState>>,
    form: web::Form<SmsForm>,
) -> HttpResponse {
    match data.sms_client.send("10001234", &form.to, &form.message).await {
        Ok(result) => HttpResponse::Ok().json(result),
        Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
    }
}

#[derive(serde::Deserialize)]
struct SmsForm { to: String, message: String }

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let state = Arc::new(AppState {
        sms_client: NiazpardazClient::new("YOUR_API_KEY"),
    });

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(state.clone()))
            .route("/send", web::post().to(send_sms))
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

Axum

use axum::{routing::post, Router, Json, Extension};
use niazpardaz_sms::NiazpardazClient;
use std::sync::Arc;

#[derive(serde::Deserialize)]
struct SmsRequest { to: String, message: String }

async fn send_sms(
    Extension(client): Extension<Arc<NiazpardazClient>>,
    Json(req): Json<SmsRequest>,
) -> Json<serde_json::Value> {
    match client.send("10001234", &req.to, &req.message).await {
        Ok(result) => Json(serde_json::json!({
            "batch_sms_id": result.batch_sms_id,
            "success": result.is_successful()
        })),
        Err(e) => Json(serde_json::json!({ "error": e.to_string() })),
    }
}

#[tokio::main]
async fn main() {
    let client = Arc::new(NiazpardazClient::new("YOUR_API_KEY"));

    let app = Router::new()
        .route("/send", post(send_sms))
        .layer(Extension(client));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Rocket

#[macro_use] extern crate rocket;
use niazpardaz_sms::NiazpardazClient;
use rocket::State;
use rocket::serde::json::Json;

#[derive(serde::Deserialize)]
struct SmsForm<'r> { to: &'r str, message: &'r str }

#[post("/send", data = "<form>")]
async fn send(
    client: &State<NiazpardazClient>,
    form: Json<SmsForm<'_>>,
) -> String {
    match client.send("10001234", form.to, form.message).await {
        Ok(r) => format!("BatchSmsId: {}", r.batch_sms_id),
        Err(e) => format!("Error: {}", e),
    }
}

#[launch]
fn rocket() -> _ {
    rocket::build()
        .manage(NiazpardazClient::new("YOUR_API_KEY"))
        .mount("/", routes![send])
}

Warp

use warp::Filter;
use niazpardaz_sms::NiazpardazClient;
use std::sync::Arc;

#[tokio::main]
async fn main() {
    let client = Arc::new(NiazpardazClient::new("YOUR_API_KEY"));

    let send = warp::path("send")
        .and(warp::post())
        .and(warp::body::json())
        .and(warp::any().map(move || client.clone()))
        .and_then(|body: serde_json::Value, client: Arc<NiazpardazClient>| async move {
            let to = body["to"].as_str().unwrap_or("");
            let msg = body["message"].as_str().unwrap_or("");
            match client.send("10001234", to, msg).await {
                Ok(r) => Ok::<_, warp::Rejection>(warp::reply::json(&r)),
                Err(_) => Ok(warp::reply::json(&serde_json::json!({"error": "failed"}))),
            }
        });

    warp::serve(send).run(([0, 0, 0, 0], 8080)).await;
}

Tide

use tide::Request;
use niazpardaz_sms::NiazpardazClient;

#[derive(Clone)]
struct State { sms: NiazpardazClient }

#[derive(serde::Deserialize)]
struct SmsBody { to: String, message: String }

#[async_std::main]
async fn main() -> tide::Result<()> {
    let state = State { sms: NiazpardazClient::new("YOUR_API_KEY") };
    let mut app = tide::with_state(state);

    app.at("/send").post(|mut req: Request<State>| async move {
        let body: SmsBody = req.body_json().await?;
        let result = req.state().sms.send("10001234", &body.to, &body.message).await?;
        Ok(tide::Response::builder(200).body(tide::Body::from_json(&result)?).build())
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

CLI Application

use niazpardaz_sms::NiazpardazClient;

#[tokio::main]
async fn main() {
    let api_key = std::env::var("NIAZPARDAZ_API_KEY")
        .expect("NIAZPARDAZ_API_KEY not set");

    let client = NiazpardazClient::new(api_key);

    let args: Vec<String> = std::env::args().collect();
    if args.len() < 4 {
        eprintln!("Usage: sms-cli <from> <to> <message>");
        std::process::exit(1);
    }

    match client.send(&args[1], &args[2], &args[3]).await {
        Ok(result) => {
            if result.is_successful() {
                println!("Sent! ID: {}", result.batch_sms_id);
            } else {
                eprintln!("Failed: {}", result.result_code);
            }
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}

تمام متدها | API Reference

متد توضیحات
send(from, to, message) ارسال پیامک تکی
send_bulk(from, to_list, message) ارسال گروهی
send_bulk_full(from, to_list, message, flash, delay) ارسال گروهی با تنظیمات کامل
send_sms_like_to_like(from, to_list, message_list) ارسال نظیر به نظیر
send_voice_otp(from, to, otp) ارسال OTP صوتی
get_batch_delivery(batch_sms_id, page, size) گزارش تحویل گروهی
get_delivery_like_to_like(sms_id) گزارش تحویل نظیر به نظیر
get_credit() اعتبار باقیمانده
get_sender_numbers() شماره‌های فرستنده
get_inbox_count(is_read) تعداد پیام‌های دریافتی
get_messages(type, from, page, size) لیست پیامک‌ها
get_messages_by_date_range(type, from, from_date, to_date) پیامک‌ها بر اساس بازه
extract_telecom_blacklist_numbers(numbers) استخراج شماره‌های لیست سیاه
number_is_in_telecom_blacklist(number) بررسی لیست سیاه
check_sms_content(message) بررسی محتوای پیامک

تمام متدها هم در NiazpardazClient (async) و هم در BlockingClient (sync) موجودند.


مدیریت خطا | Error Handling

use niazpardaz_sms::{NiazpardazClient, NiazpardazError};

async fn example(client: &NiazpardazClient) {
    match client.send("10001234", "09123456789", "تست").await {
        Ok(result) => println!("Success: {}", result.batch_sms_id),

        Err(NiazpardazError::Api { code, message }) => {
            // خطای منطقی API (اعتبار ناکافی، شماره نامعتبر و...)
            eprintln!("API Error (code {}): {}", code, message);
        }

        Err(NiazpardazError::Network(e)) => {
            // خطای شبکه (timeout, DNS, ...)
            eprintln!("Network Error: {}", e);
        }

        Err(NiazpardazError::Json(e)) => {
            // خطا در پردازش JSON
            eprintln!("JSON Error: {}", e);
        }

        Err(e) => {
            // خطای عمومی
            eprintln!("Error: {}", e);
        }
    }
}

نیازمندی‌ها | Requirements

  • Rust 1.75 یا بالاتر
  • وابستگی‌ها: reqwest, serde, serde_json, thiserror

انتشار در crates.io

cargo login YOUR_CRATES_IO_TOKEN
cargo publish

مجوز | License

MIT License — LICENSE

پشتیبانی | Support