leetify

Crates.ioleetify
lib.rsleetify
version0.1.1
created_at2025-12-07 21:51:04.084928+00
updated_at2025-12-07 22:21:25.142221+00
descriptionA Rust client library for the Leetify Public CS API
homepagehttps://github.com/muijf/leetify
repositoryhttps://github.com/muijf/leetify
max_upload_size
id1972316
size232,223
Milan de Kruijf (milandekruijf)

documentation

https://docs.rs/leetify

README

Leetify Banner

CI crates.io docs.rs license

A Rust client library for the Leetify Public CS API

Type-safe, async API client with comprehensive error handling, builder pattern configuration, and an ergonomic extended Player API.

DocumentationExamplesContributingCode of Conduct


Key Features: Type-safe IDs • Builder pattern • Extended Player API • Comprehensive error handling • Full async/await support • Automatic JSON deserialization • API key validation • Feature flags for customization


Table of Contents


Installation

Add this to your Cargo.toml:

[dependencies]
leetify = "0.1.1"
tokio = { version = "1", features = ["full"] }

Note: This library requires an async runtime. Tokio is recommended, but any async runtime compatible with reqwest will work.

Feature Flags

Most features are optional to keep the core library lightweight. Enable only what you need.

Core Features:

  • default - Enables all default features (player, rustls-tls)
  • player - Enables the extended Player API for a more ergonomic interface
  • rustls-tls - Uses rustls as the TLS backend for reqwest (default, recommended)
  • native-tls - Uses native-tls as the TLS backend for reqwest

Quick examples:

# Default (includes player API and rustls)
leetify = "0.1.1"

# Minimal setup (without Player API)
leetify = { version = "0.1.1", default-features = false, features = ["rustls-tls"] }

# With native-tls instead of rustls
leetify = { version = "0.1.1", default-features = false, features = ["player", "native-tls"] }

# Custom feature combination
leetify = { version = "0.1.1", default-features = false, features = ["player", "rustls-tls"] }

Note: The player feature enables the extended Player API which provides a more ergonomic interface. The core Client API is always available.

Quick Start

use leetify::{Client, Id};

#[tokio::main]
async fn main() -> Result<(), leetify::Error> {
    // Create a client
    let client = Client::new();

    // Get player profile by Steam64 ID
    let profile = client
        .get_profile(Id::Steam64("76561198283431555".into()))
        .await?;

    println!("Player: {}", profile.name);
    println!("Winrate: {:.2}%", profile.winrate * 100.0);

    Ok(())
}

Output:

Player: PlayerName
Winrate: 52.34%

For more examples and usage patterns, see the examples.

API Methods

Get Player Profile

use leetify::{Client, Id};

let client = Client::new();

// By Steam64 ID
let profile = client
    .get_profile(Id::Steam64("76561198283431555".into()))
    .await?;

// By Leetify ID (UUID format)
let profile = client
    .get_profile(Id::Leetify("5ea07280-2399-4c7e-88ab-f2f7db0c449f".into()))
    .await?;

// Using automatic conversion (UUID format -> Leetify, numeric strings -> Steam64)
let id: Id = "76561198283431555".into();
let profile = client.get_profile(id).await?;

Get Match History

use leetify::{Client, Id};

let client = Client::new();

let matches = client
    .get_profile_matches(Id::Steam64("76561198283431555".into()))
    .await?;

for match_details in matches {
    println!("Match: {} on {}", match_details.id, match_details.map_name);
}

Get Match Details

use leetify::{Client, DataSource};

let client = Client::new();

// By game ID
let match_details = client
    .get_match_by_game_id("match-id-123".to_string())
    .await?;

// By data source
let match_details = client
    .get_match_by_data_source(DataSource::FACEIT, "faceit-match-id")
    .await?;

Validate API Key

use leetify::Client;

let client = Client::with_api_key("your-api-key".to_string());

match client.validate_api_key().await {
    Ok(()) => println!("API key is valid"),
    Err(e) => eprintln!("Validation failed: {}", e),
}

Using an API Key

API keys provide higher rate limits. You can obtain one at https://leetify.com/app/developer.

use leetify::Client;

let client = Client::with_api_key("your-api-key".to_string());

Builder Pattern

For advanced configuration:

use leetify::Client;
use std::time::Duration;

let client = Client::builder()
    .api_key("your-api-key")
    .timeout(Duration::from_secs(60))
    .base_url("https://custom-api.example.com")
    .build()?;

Extended API

The extended Player API provides a more ergonomic interface by storing the player ID, allowing you to call methods without passing it each time. Enable the player feature to use this API.

For a more ergonomic API, use the Player struct which stores the id and allows you to call methods without passing it each time:

use leetify::{Client, Id};

let client = Client::new();
let player = client.player(Id::Steam64("76561198283431555".into()));

// Get profile
let profile = player.profile().await?;

// Get matches
let matches = player.matches().await?;

Type Safety

The library provides type-safe wrappers to prevent mixing up different ID types:

  • Id - Enum for player identification (either Steam64 or Leetify)
  • Steam64Id - For Steam 64-bit IDs (numeric strings, typically 17 digits)
  • LeetifyId - For Leetify user IDs (UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
  • DataSource - Enum for data sources (FACEIT, Matchmaking, etc.)

The Id enum can be created from strings with automatic detection:

  • Strings matching UUID format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are treated as Leetify IDs
  • Numeric strings (15+ digits) are treated as Steam64 IDs
  • You can also explicitly use the enum variants (Id::Steam64 or Id::Leetify) for clarity

Error Handling

The library provides comprehensive error types:

use leetify::Error;

match result {
    Ok(data) => println!("Success: {:?}", data),
    Err(Error::MissingParameter(msg)) => eprintln!("Missing required parameter: {}", msg),
    Err(Error::InvalidApiKey) => eprintln!("Invalid API key"),
    Err(Error::Http(e)) => eprintln!("HTTP error: {}", e),
    Err(Error::Api(status, msg)) => eprintln!("API error {}: {}", status, msg),
    Err(e) => eprintln!("Other error: {}", e),
}

Examples

Run any example with: cargo run --example <name>

Core Examples:

Basic Usage Example

use leetify::{Client, Id, DataSource};

#[tokio::main]
async fn main() -> Result<(), leetify::Error> {
    let client = Client::new();

    // Get profile
    let profile = client
        .get_profile(Id::Steam64("76561198283431555".into()))
        .await?;

    // Get matches
    let matches = client
        .get_profile_matches(Id::Steam64("76561198283431555".into()))
        .await?;

    // Get match details
    let match_details = client
        .get_match_by_data_source(DataSource::FACEIT, "faceit-match-id")
        .await?;

    Ok(())
}

Extended Player API Example

use leetify::{Client, Id};

#[tokio::main]
async fn main() -> Result<(), leetify::Error> {
    let client = Client::new();
    let player = client.player(Id::Steam64("76561198283431555".into()));

    // No need to pass ID each time
    let profile = player.profile().await?;
    let matches = player.matches().await?;

    Ok(())
}

Development

Format code:

cargo fmt --all

Formats all Rust code according to the official style guide.

Lint code:

cargo clippy --all-targets --all-features -- -D warnings

Runs Clippy linter with all targets and features enabled, treating warnings as errors.

Run tests:

cargo test --all-features

Runs all tests with all features enabled to ensure comprehensive coverage.

Run doc tests:

cargo test --doc

Runs documentation tests to ensure all code examples compile and work correctly.

Editor setup: Recommended extensions are available in .vscode/extensions.json. See CONTRIBUTING.md for development guidelines and pre-commit hooks.

Rate Limits

  • Without an API key: Subject to increased rate limits
  • With an API key: Higher rate limits (check Leetify documentation for current limits)

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Commit count: 0

cargo fmt