topgg 1.0.3

The official Rust wrapper for the Top.gg API
Documentation

topgg crates.io crates.io downloads license BLAZINGLY FAST!!!

The official Rust SDK for the Top.gg API.

Getting Started

Make sure to have a Top.gg API token handy, you can have an API token if you own a listed Discord bot on Top.gg (open the edit page, see in Webhooks section) then add the following to your Cargo.toml's dependencies:

topgg = "1.0"

Features

This library provides several feature flags that can be enabled/disabled in Cargo.toml. Such as:

  • api: Interacting with the Top.gg API and accessing the top.gg/api/* endpoints. (enabled by default)
    • autoposter: Automating the process of periodically posting bot statistics to the Top.gg API.
  • webhook: Accessing the serde deserializable topgg::Vote struct.
    • actix: Wrapper for working with the actix-web web framework.
    • axum: Wrapper for working with the axum web framework.
    • rocket: Wrapper for working with the rocket web framework.
    • warp: Wrapper for working with the warp web framework.

Examples

More things can be read on the documentation.

use topgg::Client;

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);
  
  let user = client.get_user(661200758510977084u64).await.unwrap();
  
  assert_eq!(user.username, "null");
  assert_eq!(user.discriminator, "8626");
  assert_eq!(user.id, 661200758510977084u64);
  
  println!("{:?}", user);
}
use topgg::Client;

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);
  
  let bot = client.get_bot(264811613708746752u64).await.unwrap();
  
  assert_eq!(bot.username, "Luca");
  assert_eq!(bot.discriminator, "1375");
  assert_eq!(bot.id, 264811613708746752u64);
  
  println!("{:?}", bot);
}
use topgg::{Client, Filter, Query};

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);
  
  // inputting a string searches a bot that matches that username
  for bot in client.get_bots("shiro").await.unwrap() {
    println!("{:?}", bot);
  }

  // advanced query with filters
  let filter = Filter::new()
    .username("shiro")
    .certified(true);

  let query = Query::new()
    .limit(250)
    .skip(50)
    .filter(filter);

  for bot in client.get_bots(query).await.unwrap() {
    println!("{:?}", bot);
  }
}
use topgg::{Client, NewStats};

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);

  let server_count = 1234; // be TRUTHFUL!
  let shard_count = 10;

  let stats = NewStats::count_based(server_count, Some(shard_count));

  client.post_stats(stats).await.unwrap();
}
use topgg::Client;

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);

  if client.has_voted(661200758510977084u64).await.unwrap() {
    println!("checks out");
  }
}

In your Cargo.toml:

[dependencies]
topgg = { version = "1.0", features = ["autoposter"] }

In your code:

use topgg::{Autoposter, Client, NewStats};

#[tokio::main]
async fn main() {
  let token = env!("TOPGG_TOKEN").to_owned();
  let client = Client::new(token);

  // make sure to make this autoposter instance live
  // throughout most of the bot's lifetime to keep running!
  let autoposter = client.new_autoposter(1800);

  // ... then in some on ready/new guild event ...
  let server_count = 12345;
  let stats = NewStats::count_based(server_count, None);
  autoposter.feed(stats).await;
}

In your Cargo.toml:

[dependencies]
topgg = { version = "1.0", default-features = false, features = ["actix"] }

In your code:

use actix_web::{post, App, HttpServer, Responder};
use std::io;

#[post("/dblwebhook")]
async fn webhook(vote: topgg::IncomingVote) -> impl Responder {
  match vote.authenticate(env!("TOPGG_WEBHOOK_PASSWORD")) {
    Some(vote) => /* your application logic here... */,
    _ => /* handle 401 here... */,
  }
}

#[tokio::main]
async fn main() -> io::Result<()> {
  HttpServer::new(|| {
    App::new().service(webhook)
  })
  .bind(("127.0.0.1", 8080))?
  .run()
  .await
}

In your Cargo.toml:

[dependencies]
topgg = { version = "1.0", default-features = false, features = ["axum"] }

In your code:

use axum::{Router, Server};
use std::net::SocketAddr;

struct MyVoteHandler {}

#[async_trait::async_trait]
impl topgg::VoteHandler for MyVoteHandler {
  async fn voted(&self, vote: topgg::Vote) {
    // your application logic here
  }
}

#[tokio::main]
async fn main() {
  let password = env!("TOPGG_WEBHOOK_PASSWORD").to_owned();
  let state = MyVoteHandler {};
  
  let app = Router::new()
    .nest("/dblwebhook", topgg::axum::webhook(password, state));
  
  let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

  Server::bind(&addr)
    .serve(app.into_make_service())
    .await
    .unwrap();
}

In your Cargo.toml:

[dependencies]
topgg = { version = "1.0", default-features = false, features = ["rocket"] }

In your code:

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;

use rocket::http::Status;

#[post("/", data = "<vote>")]
fn webhook(vote: topgg::IncomingVote) -> Status {
  match vote.authenticate(env!("TOPGG_WEBHOOK_PASSWORD")) {
    Some(vote) => /* your application logic here... */,
    _ => /* handle 401 here... */,
  }
}

fn main() {
  rocket::ignite()
    .mount("/dblwebhook", routes![webhook])
    .launch();
}

In your Cargo.toml:

[dependencies]
topgg = { version = "1.0", default-features = false, features = ["warp"] }

In your code:

struct MyVoteHandler {}

#[async_trait::async_trait]
impl topgg::VoteHandler for MyVoteHandler {
  async fn voted(&self, vote: topgg::Vote) {
    // your application logic here
  }
}

#[tokio::main]
async fn main() {
  let password = env!("TOPGG_WEBHOOK_PASSWORD").to_owned();
  let state = MyVoteHandler {};
  
  // POST /dblwebhook
  let webhook = topgg::warp::webhook("dblwebhook", password, state);   
  let routes = warp::post().and(webhook);

  warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}