#osu #api #wrapper

rosu

A fully functional wrapper for the osu! API

14 releases (4 breaking)

0.5.0 Jan 19, 2021
0.4.0 Nov 27, 2020
0.3.3 Oct 25, 2020
0.3.2 Aug 26, 2020
0.1.1 Feb 25, 2020

#5 in #osu

Download history 2/week @ 2021-06-03 18/week @ 2021-06-10 2/week @ 2021-07-01 1/week @ 2021-07-08 16/week @ 2021-07-15 3/week @ 2021-07-22 30/week @ 2021-07-29 15/week @ 2021-08-05 18/week @ 2021-08-12 1/week @ 2021-08-19 1/week @ 2021-08-26 1/week @ 2021-09-02 2/week @ 2021-09-09

78 downloads per month

MIT license

140KB
3.5K SLoC

crates.io Released API docs

rosu

rosu is a rust wrapper for osu!.

The wrapper provides access to the osu!api's beatmap, user, score, user-best, user-recent, and match endpoints. Note: Only v1 of the osu!api is supported.

An API key can be generated here.

Simply initialize an Osu client with the api key, call any of its get_* methods and await its result.

Examples

use chrono::{offset::TimeZone, DateTime, Utc};
use rosu::{
    model::*,
    Osu, OsuResult,
};

#[tokio::main]
async fn main() -> OsuResult<()> {
    // Initialize the client
    let osu = Osu::new("osu_api_key");
    // If `cache` feature enabled:
    // let osu = Osu::new("osu_api_key", redis_pool, rosu::OsuCached::User);

    // --- Retrieving top scores ---

    // Accumulate all important arguments for the request
    let request = osu.top_scores("Badewanne3")
        .mode(GameMode::MNA)
        .limit(4);
    // Await the request
    let mut scores: Vec<Score> = request.await?;
    match scores.pop() {
        Some(score) => {
            // Retrieve user of the score
            let user = score.get_user(&osu).mode(GameMode::STD).await?;
            // ...
        }
        None => println!("No top scores found"),
    }

    // --- Retrieving beatmaps ---

    let since_date: DateTime<Utc> = Utc
        .datetime_from_str("2018-11-13 23:01:28", "%Y-%m-%d %H:%M:%S")
        .unwrap();
    let request = osu.beatmaps()
        .mode(GameMode::MNA)
        .limit(3)
        .since(since_date)
        .mapset_id(945496);
    let mut maps: Vec<Beatmap> = request.await?;
    if let Some(map) = maps.pop() {
        let leaderboard: Vec<Score> = map.get_global_leaderboard(&osu).limit(13).await?;
        // ...
    }

    // --- Retrieving user ---

    let user: Option<User> = osu.user("Badewanne3").await?;
    // ...

    // --- Retrieving match ---

    let osu_match: Match = osu.osu_match(58494587).await?;
    // ...

    Ok(())
}

Features

Flag Description deps
serialize Provides serialization for all structs in the models dir serde-repr
metrics Make the client count each request type and enable a method on the client to get a prometheus::IntCounterVec prometheus
cache Cache API results through a redis connection for a given duration darkredis, serialize

Error handling

OsuErrors are nested through their source errors. To read them, one can use a small unwind macro such as:

#[macro_export]
macro_rules! unwind_error {
    ($log:ident, $err:ident, $($arg:tt)+) => {
        {
            $log!($($arg)+, $err);
            let mut err: &dyn ::std::error::Error = &$err;
            while let Some(source) = err.source() {
                $log!("  - caused by: {}", source);
                err = source;
            }
        }
    };
}

use rosu::{Osu, OsuResult, model::GameMode};

#[tokio::main]
async fn main() {
    let osu = Osu::new("osu_api_key");
    let mode = GameMode::STD;
    if let Err(why) = osu.user("badewanne3").mode(mode).await {
        unwind_error!(println, why, "Error while retrieving user for mode {}: {}", mode);
    }
}

Dependencies

~6–11MB
~233K SLoC