| Crates.io | tlw_irus |
| lib.rs | tlw_irus |
| version | 0.1.6 |
| created_at | 2025-11-27 19:00:55.445+00 |
| updated_at | 2025-12-19 01:59:47.559807+00 |
| description | Cliente Rust para a API Suri - plataforma de atendimento e e-commerce |
| homepage | |
| repository | https://github.com/nextlw/tlw_irus |
| max_upload_size | |
| id | 1954271 |
| size | 789,058 |
Cliente Rust para a API Suri - plataforma de atendimento e e-commerce via WhatsApp.
Adicione ao seu Cargo.toml:
[dependencies]
tlw_irus = "0.1.2"
tokio = { version = "1", features = ["full"] }
use suri::{SuriClient, SuriConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configuracao do cliente
// OBRIGATÓRIO: Configure as variáveis de ambiente antes:
// export SURI_BASE_URL="https://api.suri.com.br"
// export SURI_API_TOKEN="seu_token_aqui"
let config = SuriConfig::from_env()
.expect("Variáveis de ambiente não configuradas");
let client = SuriClient::new(config);
// Listar produtos
let products = client.shop()
.list_products(Default::default())
.await?;
for product in products.data {
println!("{}: R$ {:.2}", product.name, product.price.unwrap_or(0.0));
}
Ok(())
}
use suri::{Product, BatchProductsRequest, ListProductsRequest};
// Criar produto
let product = Product::new("Meu Produto")
.with_price(99.90)
.with_stock(100)
.with_description("Descricao do produto");
client.shop().create_product(&product.into()).await?;
// Listar produtos com paginacao
let response = client.shop()
.list_products(ListProductsRequest {
per_page: Some(100),
..Default::default()
})
.await?;
// Batch de produtos (criar/atualizar em massa)
let produtos = vec![
Product::new("Produto 1").with_price(10.0).with_external_id("SKU001"),
Product::new("Produto 2").with_price(20.0).with_external_id("SKU002"),
];
let batch = client.shop()
.batch_products(BatchProductsRequest::upsert(produtos))
.await?;
// Aguardar conclusao do batch
let status = client.shop()
.wait_batch_completion(&batch.id, 2000, 300)
.await?;
println!("Batch concluido: {:?}", status.status);
// Atualizar precos
use suri::types::UpdatePricesRequest;
client.shop().update_prices("product_id", &UpdatePricesRequest {
price: Some(149.90),
sale_price: Some(129.90),
variants: None,
}).await?;
// Atualizar estoque
use suri::types::UpdateStocksRequest;
use suri::Stock;
client.shop().update_stocks("product_id", &UpdateStocksRequest {
stock: Some(Stock {
quantity: 50,
available: 50,
reserved: 0,
track_inventory: true,
allow_backorder: false,
}),
variants: None,
}).await?;
use suri::{Category, CreateCategoryRequest};
// Listar categorias
let categories = client.shop().list_categories().await?;
// Criar categoria
let category = client.shop().create_category(&CreateCategoryRequest {
name: "Eletronicos".to_string(),
description: Some("Produtos eletronicos".to_string()),
parent_id: None,
image_url: None,
order: Some(1),
store: None,
}).await?;
use suri::{Collection, CreateCollectionRequest, CollectionType};
// Listar colecoes
let collections = client.shop().list_collections().await?;
// Criar colecao manual
let collection = Collection::new("Promocoes")
.with_product("product_id_1")
.with_product("product_id_2");
client.shop().create_collection(&collection.into()).await?;
use suri::{ListOrdersRequest, OrderStatus, UpdateOrderLogisticRequest};
// Listar pedidos
let orders = client.shop()
.list_orders(ListOrdersRequest {
status: Some(OrderStatus::Paid),
per_page: Some(50),
..Default::default()
})
.await?;
// Obter pedido especifico
let order = client.shop().get_order("order_id").await?;
// Atualizar logistica
client.shop().update_order_logistic(&UpdateOrderLogisticRequest {
order_id: "order_id".to_string(),
tracking_code: Some("BR123456789".to_string()),
carrier: Some("Correios".to_string()),
status: Some(OrderStatus::Shipped),
..Default::default()
}).await?;
// Marcar como pago
use suri::MarkOrderPaidRequest;
client.shop().mark_order_paid(&MarkOrderPaidRequest {
order_id: "order_id".to_string(),
transaction_id: Some("txn_123".to_string()),
..Default::default()
}).await?;
// Cancelar pedido
use suri::CancelOrderRequest;
client.shop().cancel_order(&CancelOrderRequest {
order_id: "order_id".to_string(),
reason: Some("Cliente solicitou cancelamento".to_string()),
refund: Some(true),
}).await?;
use suri::{ImportContactRequest, AddVariableRequest, RequestAttendanceRequest};
// Importar contato
let contact = client.contacts()
.import(ImportContactRequest {
phone: "5511999999999".to_string(),
name: Some("Joao Silva".to_string()),
email: Some("joao@email.com".to_string()),
channel: "channel_id".to_string(),
variables: None,
tags: Some(vec!["cliente-vip".to_string()]),
})
.await?;
// Obter contato
let contact = client.contacts().get("contact_id").await?;
// Adicionar variavel
client.contacts()
.add_variable("contact_id", AddVariableRequest {
name: "ultima_compra".to_string(),
value: serde_json::json!("2024-01-15"),
})
.await?;
// Solicitar atendimento
client.contacts()
.request_attendance("contact_id", RequestAttendanceRequest {
department: Some("vendas_id".to_string()),
attendant: None,
message: Some("Cliente precisa de ajuda".to_string()),
})
.await?;
use suri::SendMessageRequest;
// Enviar texto simples
client.messages()
.send_text("contact_id", "Ola! Como posso ajudar?")
.await?;
// Enviar imagem com caption
client.messages()
.send(SendMessageRequest::image("contact_id", "https://example.com/img.jpg")
.with_caption("Confira nossa promocao!"))
.await?;
// Responder mensagem
client.messages()
.send(SendMessageRequest::text("contact_id", "Obrigado pelo contato!")
.with_reply_to("message_id"))
.await?;
// Listar templates
let templates = client.templates().list().await?;
// Obter template especifico
let template = client.templates().get("template_id").await?;
use suri::{CreateCampaignRequest, CampaignAudience};
// Listar campanhas
let campaigns = client.campaigns().list().await?;
// Criar campanha
let campaign = client.campaigns()
.create(CreateCampaignRequest {
name: "Campanha de Natal".to_string(),
description: Some("Promocoes de fim de ano".to_string()),
channel: "channel_id".to_string(),
template: "template_id".to_string(),
template_params: Some(vec!["{{1}}".to_string()]),
audience: CampaignAudience {
tags: Some(vec!["clientes-vip".to_string()]),
..Default::default()
},
schedule: None,
action: None,
})
.await?;
// Iniciar campanha
client.campaigns().start("campaign_id").await?;
// Pausar campanha
client.campaigns().pause("campaign_id").await?;
// Cancelar campanha
client.campaigns().cancel("campaign_id").await?;
// Listar departamentos
let departments = client.departments().list().await?;
// Listar atendentes
let attendants = client.attendants().list().await?;
// Listar canais
let channels = client.channels().list().await?;
// Obter canal especifico
let channel = client.channels().get("channel_id").await?;
// Listar flows
let flows = client.flows().list().await?;
// Obter flow especifico
let flow = client.flows().get("flow_id").await?;
use suri::{ListAttendancesRequest, AttendanceStatusType};
// Listar atendimentos ativos
let attendances = client.attendances()
.list(ListAttendancesRequest {
status: Some(AttendanceStatusType::Active),
per_page: Some(50),
..Default::default()
})
.await?;
use suri::{SetWebhookRequest, WebhookEvent};
// Configurar webhook
client.shop().set_webhook(&SetWebhookRequest {
url: "https://meusite.com/webhook".to_string(),
events: Some(vec![
WebhookEvent::OrderCreated,
WebhookEvent::OrderPaid,
WebhookEvent::OrderShipped,
]),
active: Some(true),
secret: Some("meu_secret".to_string()),
store: None,
}).await?;
use suri::error::SuriError;
match client.shop().get_product("invalid_id").await {
Ok(product) => println!("Produto: {}", product.name),
Err(SuriError::NotFoundError { resource }) => {
println!("Produto nao encontrado: {}", resource);
}
Err(SuriError::RateLimitError { retry_after_secs }) => {
println!("Rate limit, aguarde {} segundos", retry_after_secs);
}
Err(SuriError::ValidationError { message, details }) => {
println!("Erro de validacao: {}", message);
if let Some(d) = details {
for err in d.field_errors {
println!(" - {}: {}", err.field, err.message);
}
}
}
Err(e) => println!("Erro: {}", e),
}
use std::time::Duration;
// OBRIGATÓRIO: Configure as variáveis de ambiente antes:
// export SURI_BASE_URL="https://api.suri.com.br"
// export SURI_API_TOKEN="seu_token_aqui"
let config = SuriConfig::from_env()
.expect("Variáveis de ambiente não configuradas")
.with_timeout(Duration::from_secs(60)) // Timeout de 60 segundos
.with_max_retries(5) // 5 tentativas em caso de erro
.with_rate_limit(20) // 20 requisicoes por segundo
.with_user_agent("MeuApp/1.0"); // User-Agent personalizado
let client = SuriClient::new(config);
tlw_irus/
├── Cargo.toml
├── README.md
└── src/
├── lib.rs # Re-exports publicos
├── client.rs # Cliente HTTP principal
├── error.rs # Tipos de erro (SuriError)
├── config.rs # Configuracao do cliente
├── types/ # Tipos de dados
│ ├── mod.rs
│ ├── user.rs
│ ├── channel.rs
│ ├── department.rs
│ ├── attendant.rs
│ ├── message.rs
│ ├── template.rs
│ ├── campaign.rs
│ ├── flow.rs
│ ├── attendance.rs
│ └── shop/
│ ├── mod.rs
│ ├── product.rs
│ ├── category.rs
│ ├── collection.rs
│ ├── order.rs
│ ├── batch.rs
│ └── store.rs
└── api/ # Implementacoes de endpoints
├── mod.rs
├── shop.rs
├── contacts.rs
├── messages.rs
├── templates.rs
├── campaigns.rs
├── departments.rs
├── attendants.rs
├── channels.rs
├── flows.rs
└── attendances.rs
MIT