Initial commit
This commit is contained in:
commit
8f4da14603
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
1175
Cargo.lock
generated
Normal file
1175
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["Sakuhl <2012collector@gmail.com>"]
|
||||||
|
name = "wynnrobot"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
reqwest = "0.8.1"
|
||||||
|
serde = "1.0.24"
|
||||||
|
serde_derive = "1.0.24"
|
||||||
|
serde_json = "1.0.8"
|
||||||
|
serenity = "0.4.5"
|
262
src/main.rs
Normal file
262
src/main.rs
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
extern crate serenity;
|
||||||
|
|
||||||
|
use serenity::prelude::*;
|
||||||
|
use serenity::model::*;
|
||||||
|
|
||||||
|
extern crate reqwest;
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate serde_json;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Guild {
|
||||||
|
pub name: String,
|
||||||
|
pub prefix: String,
|
||||||
|
pub members: Vec<Member>,
|
||||||
|
pub xp: f64,
|
||||||
|
pub level: u64,
|
||||||
|
pub created: String,
|
||||||
|
pub created_friendly: String,
|
||||||
|
pub territories: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Member {
|
||||||
|
pub name: String,
|
||||||
|
pub rank: Rank,
|
||||||
|
pub contributed: u64,
|
||||||
|
pub joined: String,
|
||||||
|
pub joined_friendly: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum Rank {
|
||||||
|
Owner,
|
||||||
|
Chief,
|
||||||
|
Captain,
|
||||||
|
Recruiter,
|
||||||
|
Recruit
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Player {
|
||||||
|
pub username: String,
|
||||||
|
pub rank: String,
|
||||||
|
pub tag: String,
|
||||||
|
pub displayTag: bool,
|
||||||
|
pub veteran: bool,
|
||||||
|
pub playtime: u64,
|
||||||
|
pub first_join: String,
|
||||||
|
pub last_join: String,
|
||||||
|
pub first_join_friendly: String,
|
||||||
|
pub last_join_friendly: String,
|
||||||
|
pub current_server: String,
|
||||||
|
pub global: GlobalPlayerInfo,
|
||||||
|
pub classes: HashMap<String, Class>,
|
||||||
|
pub wizard_fortress: WFPlayerInfo,
|
||||||
|
pub rankings: PlayerRankings,
|
||||||
|
pub guild: PlayerGuildInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct GlobalPlayerInfo {
|
||||||
|
pub items_identified: u64,
|
||||||
|
pub mobs_killed: u64,
|
||||||
|
pub pvp_kills: u64,
|
||||||
|
pub pvp_deaths: u64,
|
||||||
|
pub chests_found: u64,
|
||||||
|
pub blocks_walked: u64,
|
||||||
|
pub logins: u64,
|
||||||
|
pub deaths: u64,
|
||||||
|
pub total_level: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub struct Class {
|
||||||
|
pub level: u64,
|
||||||
|
pub xp: f64,
|
||||||
|
pub dungeons: Value,
|
||||||
|
pub quests: Vec<String>,
|
||||||
|
pub dungeonsAmount: String,
|
||||||
|
pub questsAmount: String,
|
||||||
|
pub skills: Value,
|
||||||
|
pub items_identified: u64,
|
||||||
|
pub mobs_killed: u64,
|
||||||
|
pub pvp_kills: u64,
|
||||||
|
pub pvp_deaths: u64,
|
||||||
|
pub chests_found: u64,
|
||||||
|
pub blocks_walked: u64,
|
||||||
|
pub logins: u64,
|
||||||
|
pub deaths: u64,
|
||||||
|
pub events_won: u64,
|
||||||
|
/// in minutes
|
||||||
|
pub playtime: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct WFPlayerInfo {
|
||||||
|
pub kills: u64,
|
||||||
|
pub deaths: u64,
|
||||||
|
pub wins: u64,
|
||||||
|
pub losses: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct PlayerRankings {
|
||||||
|
pub pvp: u64,
|
||||||
|
pub player: u64,
|
||||||
|
pub guild: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct PlayerGuildInfo {
|
||||||
|
pub name: String,
|
||||||
|
pub rank: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Handler;
|
||||||
|
|
||||||
|
impl EventHandler for Handler {
|
||||||
|
// Set a handler for the `on_message` event - so that whenever a new message
|
||||||
|
// is received - the closure (or function) passed will be called.
|
||||||
|
//
|
||||||
|
// Event handlers are dispatched through multi-threading, and so multiple
|
||||||
|
// of a single event can be dispatched simultaneously.
|
||||||
|
fn on_message(&self, _: Context, msg: Message) {
|
||||||
|
if msg.content.starts_with("wc!guild ") {
|
||||||
|
let guild = &msg.content[9..];
|
||||||
|
let resp = reqwest::get(&format!("https://api.wynncraft.com/public_api.php?action=guildStats&command={}", guild)).unwrap();
|
||||||
|
assert!(resp.status().is_success());
|
||||||
|
|
||||||
|
if let Ok(guild) = serde_json::from_reader(resp) {
|
||||||
|
let guild: Guild = guild;
|
||||||
|
|
||||||
|
let resp = reqwest::get("https://api.wynncraft.com/public_api.php?action=territoryList").unwrap();
|
||||||
|
assert!(resp.status().is_success());
|
||||||
|
|
||||||
|
let territories: Value = serde_json::from_reader(resp).unwrap();
|
||||||
|
|
||||||
|
let mut message = String::new();
|
||||||
|
for value in territories.get("territories").unwrap().as_object().unwrap().values() {
|
||||||
|
if value.get("guild").unwrap().as_str().unwrap() == guild.name {
|
||||||
|
message.push_str(&format!("
|
||||||
|
**Territory**: {}",
|
||||||
|
value.get("territory").unwrap().as_str().unwrap()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.channel_id.say(
|
||||||
|
format!(
|
||||||
|
"**Guild**: {}
|
||||||
|
**prefix**: {}
|
||||||
|
**Created**: {}
|
||||||
|
**Level**: {}",
|
||||||
|
guild.name,
|
||||||
|
guild.prefix,
|
||||||
|
guild.created_friendly,
|
||||||
|
guild.level
|
||||||
|
) + &message
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
} else if msg.content.starts_with("wc!territory ") {
|
||||||
|
let territory = &msg.content[13..];
|
||||||
|
|
||||||
|
let resp = reqwest::get("https://api.wynncraft.com/public_api.php?action=territoryList").unwrap();
|
||||||
|
assert!(resp.status().is_success());
|
||||||
|
|
||||||
|
let territories: Value = serde_json::from_reader(resp).unwrap();
|
||||||
|
|
||||||
|
let mut message = String::new();
|
||||||
|
for value in territories.get("territories").unwrap().as_object().unwrap().values() {
|
||||||
|
if value.get("territory").unwrap().as_str().unwrap().contains(territory) {
|
||||||
|
message.push_str(&format!("
|
||||||
|
**Territory**: {}
|
||||||
|
**Owner**: {}
|
||||||
|
**Acquired at**: {}
|
||||||
|
",
|
||||||
|
value.get("territory").unwrap().as_str().unwrap(),
|
||||||
|
value.get("guild").unwrap().as_str().unwrap(),
|
||||||
|
value.get("acquired").unwrap().as_str().unwrap()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !message.is_empty() {
|
||||||
|
msg.channel_id.say(
|
||||||
|
message
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
} else if msg.content.starts_with("wc!status") {
|
||||||
|
let resp = reqwest::get("https://api.wynncraft.com/public_api.php?action=onlinePlayersSum").unwrap();
|
||||||
|
|
||||||
|
let value: Value = serde_json::from_reader(resp).unwrap();
|
||||||
|
|
||||||
|
msg.channel_id.say(
|
||||||
|
format!("{} players online", value.get("players_online").unwrap().as_u64().unwrap())
|
||||||
|
).unwrap();
|
||||||
|
} else if msg.content.starts_with("wc!player ") {
|
||||||
|
let player = &msg.content[10..];
|
||||||
|
|
||||||
|
let resp = reqwest::get(&format!("https://api.wynncraft.com/public_api.php?action=playerStats&command={}", player)).unwrap();
|
||||||
|
|
||||||
|
let player: Player = serde_json::from_reader(resp).unwrap();
|
||||||
|
|
||||||
|
msg.channel_id.say(
|
||||||
|
format!(
|
||||||
|
"**Player name**: {}
|
||||||
|
**Guild**: {}
|
||||||
|
**Playtime**: {} hours
|
||||||
|
**Kills**: {} mobs & {} players
|
||||||
|
**Chests looted**: {}
|
||||||
|
**Total level**: {}",
|
||||||
|
player.username,
|
||||||
|
player.guild.name,
|
||||||
|
player.playtime / 60,
|
||||||
|
player.global.mobs_killed, player.global.pvp_kills,
|
||||||
|
player.global.chests_found,
|
||||||
|
player.classes.iter().map(|(_, x)| x.level).sum::<u64>()
|
||||||
|
)
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a handler to be called on the `on_ready` event. This is called when a
|
||||||
|
// shard is booted, and a READY payload is sent by Discord. This payload
|
||||||
|
// contains data like the current user's guild Ids, current user data,
|
||||||
|
// private channels, and more.
|
||||||
|
//
|
||||||
|
// In this case, just print what the current user's username is.
|
||||||
|
fn on_ready(&self, _: Context, ready: Ready) {
|
||||||
|
println!("{} is connected!", ready.user.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Configure the client with your Discord bot token in the environment.
|
||||||
|
let token = env::var("DISCORD_TOKEN").expect("DISCORD_TOKEN must be set");
|
||||||
|
|
||||||
|
// Create a new instance of the Client, logging in as a bot. This will
|
||||||
|
// automatically prepend your bot token with "Bot ", which is a requirement
|
||||||
|
// by Discord for bot users.
|
||||||
|
let mut client = Client::new(&token, Handler);
|
||||||
|
|
||||||
|
// Finally, start a single shard, and start listening to events.
|
||||||
|
//
|
||||||
|
// Shards will automatically attempt to reconnect, and will perform
|
||||||
|
// exponential backoff until it reconnects.
|
||||||
|
if let Err(why) = client.start() {
|
||||||
|
println!("Client error: {:?}", why);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user