GitXplorerGitXplorer
a

coc.rs

public
6 stars
2 forks
4 issues

Commits

List of commits on branch master.
Verified
28e5e281639a6787ec67d015df17f3b0084865b0

0.8.3

aamaanq committed a year ago
Verified
e38a54942dc57da557d8c777b197e099e9b4c383

ci: update scripts

aamaanq committed a year ago
Verified
b75ca19937975293066fed7be39aea8b3e9bcfc1

refactor!: use a manual deserialization to extract the ip on-login, and avoid calling a request to an external site

aamaanq committed a year ago
Verified
24c3e9a26c16ff6fbc0d6a7a90338c5c9d91b5df

refactor: remove mutex around client and run tests with `--test-threads 1`

aamaanq committed a year ago
Verified
c980c6fe715bb7c89f92bb0a489beeb5842af38b

feat: add ClanCapital to Village

aamaanq committed a year ago
Verified
f8fef65503dcb87e05e3a45da8d292b861acaf68

chore: clippy lints, tidying

aamaanq committed a year ago

README

The README file for this repository.

coc.rs

A Clash of Clans API wrapper written in Rust!

Key Features

  • Asynchronous code
  • Entire coverage of Clash of Clans API
  • Email and password Login
  • Ability to login with multiple accounts to handle many concurrent requests
  • API Events to track changes
  • Clash of Stats support

Getting Started

Installing

Add the version from here in your Cargo.toml

[dependencies]
coc-rs = "0.8.3"

Or with cargo add

cargo add coc-rs --features=all

Quick Example

#[tokio::main]
async fn main() {
    let credentials = CredentialsBuilder::new()
        .add_credential(env::var("username").unwrap(), env::var("password").unwrap())
        .build();
    let client = Client::new(credentials).await;

    let player = client.get_player("#2PP".to_string()).await.unwrap();

    println!("Player: {:?}", player);
}

Error Handling

#[tokio::main]
async fn main() {
    let credentials = CredentialsBuilder::new()
        .add_credential(env::var("username").unwrap(), env::var("password").unwrap())
        .build();
    let client = Client::new(credentials).await;

    let clan = match client.get_clan("#InvalidTag".to_string()).await {
        Ok(clan) => {
            println!("Clan: {:?}", clan);
        }
        Err(err) => {
            match err {
                APIError::ClientNotReady => {}, // API login hasn't been initialized yet, try not to request with milliseconds of initializing a client
                APIError::FailedGetIP(err) => {}, // A request is made to api.ipify.org to set your IP dynamically when making keys, ensure this url isn't blocked
                APIError::LoginFailed(err) => {}, // Failed to login to a Clash of Stats account
                APIError::RequestFailed(err) => {}, // Request never made it to the API
                APIError::InvalidHeader(err) => {}, // you should not get this
                APIError::BadUrl(err) => {}, // you should also not get this
                APIError::BadParameters => {}, // bad input parameters for endpoints that have this
                APIError::AccessDenied => {}, // ip changed? or accessing something you shouldn't...
                APIError::NotFound => {}, // bad input "tags" or banned players result in this
                APIError::RequestThrottled => {}, // slow down!
                APIError::UnknownError => {}, // 🤨
                APIError::InMaintenance => {}, // doofus wait until it's over!
                APIError::BadResponse(err, err_code) => {}, // Catch-all error for those that don't fall in any of the above
                APIError::InvalidParameters(err) => {}, // I caught your parameter mistake, not the API!
                APIError::InvalidTag(err) => {}, // malformed tag
                APIError::EventFailure(err) => {}, // ? maybe I should remove this..
            }
        }
    };
}

Basic Events

First a struct should be created that will implement the trait EventHandler, this is similar to how the serenity discord library does event handling.

struct Handler;

#[async_trait]
impl events::EventHandler for S {
    /// Next we bring the player method in scope, and define the behaviour
    async fn player(&self, _old_player: Option<player::Player>, _new_player: player::Player) {
        println!("Player change detected!")
    }

    /// To handle errors in the events task we need a separate error handler
    async fn handle_error(
        &self,
        _error: APIError,
        _tag: Option<String>,
        _event_type: EventType,
    ) {
        println!("Houston we have a problem!")
    }
}

Next in the main function, we will create the main function, login and add the Player and clan tags we want to keep pulling the data from API.

#[tokio::test]
async fn main() {
    //...
    /// see above example on how to create a client

    let task = tokio::spawn(async move {
        // staring the API events in a separate thread
        let mut event_builder = events::EventsListenerBuilder::new(client);
        event_builder.add_player("#2PP").add_players(vec!["#CVJLQOLR"])
            .build(Handler) // Building the EventListener struct
            .start() // starting the continuous polling of the clan/player/war endpoints
            .await;
    });
    task.await?;
}

Note: Each endpoint has a different cache refresh time. Each event will be fired at the exact time of new cache data in the API.

Features

To enable the cos feature (to use the Clash of Stats API), add this to your Cargo.toml

[dependencies]
coc-rs = { version = "0.8.3", features = ["cos"] }

To enable the extra feature (which gives you extra tools), add this to your Cargo.toml

[dependencies]
coc-rs = { version = "0.8.3", features = ["extra"] }

To enable the tracing feature (which provides built-in debugging/tracing tools), add this to your Cargo.toml

[dependencies]
coc-rs = { version = "0.8.3", features = ["tracing"] }

Or for all 3

[dependencies]
coc-rs = { version = "0.8.3", features = ["all"] }
  • Alternately with cargo add
cargo add coc-rs --features cos # or extra...or tracing...or all (you get it)

Tests

src/lib.rs contains examples as tests for every endpoint.

Contributing

Contributing is fantastic and much welcomed! If you have an issue, feel free to open an issue and start working on it.

Disclaimer

This content is not affiliated with, endorsed, sponsored, or specifically approved by Supercell and Supercell is not responsible for it. For more information see Supercell's Fan Content Policy.