pub use json::*;
use errors::Result;
use utils;
use curl::easy::{Easy, List};
use serde_json;
#[derive(Debug)]
pub struct APIStatus();
impl APIStatus {
pub fn perform(&self) -> Result<APIStatusResponse> {
let res = get_request(&Self::get_endpoint())?;
let res = res.replace(|c| match c {
'{' | '}' => true,
_ => false,
},
"")
.replace('[', "{")
.replace(']', "}");
Ok(serde_json::from_str(&res)?)
}
pub fn new() -> Self {
APIStatus {}
}
fn get_endpoint() -> String {
"https://status.mojang.com/check".to_string()
}
}
#[derive(Debug)]
pub struct NameToUUID {
username: String,
at: Option<i64>,
}
impl NameToUUID {
pub fn perform(&self) -> Result<NameUUID> {
let url = match self.at {
Some(x) => {
format!("https://api.mojang.com/users/profiles/minecraft/{}?at={}",
self.username,
x)
},
None => {
format!("https://api.mojang.com/users/profiles/minecraft/{}",
self.username)
},
};
let res = get_request(&url)?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(username: String, at: Option<i64>) -> Self {
NameToUUID {
username: username,
at: at,
}
}
}
#[derive(Debug)]
pub struct UUIDToHistory {
uuid: String,
}
impl UUIDToHistory {
pub fn perform(&self) -> Result<Vec<NameHistory>> {
let url = format!("https://api.mojang.com/user/profiles/{}/names",
self.uuid);
let res = get_request(&url)?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(uuid: String) -> Self {
UUIDToHistory {
uuid: uuid,
}
}
}
#[derive(Debug)]
pub struct PlayernamesToUUIDs {
usernames: Vec<String>,
}
impl PlayernamesToUUIDs {
fn get_endpoint() -> String {
"https://api.mojang.com/profiles/minecraft".to_string()
}
pub fn perform(&self) -> Result<Vec<NameUUID>> {
let body = serde_json::to_string(&self.usernames)?;
println!("body: {}", body);
let res = post_request(&Self::get_endpoint(), &body)?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(usernames: Vec<String>) -> Self {
if usernames.len() > 100 {
panic!("PlayernamesToUUIDs got more than 100 usernames");
}
PlayernamesToUUIDs {
usernames: usernames,
}
}
}
#[derive(Debug)]
pub struct UUIDToProfile {
uuid: String,
signed: bool,
}
impl UUIDToProfile {
pub fn perform(&self) -> Result<Profile> {
let url = if self.signed {
format!("https://sessionserver.mojang.com/session/minecraft/profile/{}?unsigned=false",
self.uuid)
} else {
format!("https://sessionserver.mojang.com/session/minecraft/profile/{}",
self.uuid)
};
let res = get_request(&url)?;
println!("res: {}", res);
Ok(serde_json::from_str(&res)?)
}
pub fn new(uuid: String, signed: bool) -> Self {
UUIDToProfile {
uuid: uuid,
signed: signed,
}
}
}
#[derive(Debug)]
pub struct BlockedServers();
impl BlockedServers {
fn get_endpoint() -> String {
"https://sessionserver.mojang.com/blockedservers".to_string()
}
pub fn perform(&self) -> Result<Vec<String>> {
let res: String = get_request(&Self::get_endpoint())?;
Ok(res.split('\n')
.filter_map(|e| if !e.is_empty() {
Some(e.to_string())
} else {
None
})
.collect())
}
pub fn new() -> Self {
BlockedServers {}
}
}
#[derive(Debug)]
pub struct Statistics {
item_sold_minecraft: bool,
prepaid_card_redeemed_minecraft: bool,
item_sold_cobalt: bool,
item_sold_scrolls: bool,
}
impl Statistics {
fn get_endpoint() -> String {
"https://api.mojang.com/orders/statistics".to_string()
}
pub fn perform(&self) -> Result<StatisticsResponse> {
let mut query: Vec<&str> = Vec::new();
if self.item_sold_minecraft {
query.push("item_sold_minecraft");
}
if self.prepaid_card_redeemed_minecraft {
query.push("prepaid_card_redeemed_minecraft");
}
if self.item_sold_cobalt {
query.push("item_sold_cobalt");
}
if self.item_sold_scrolls {
query.push("item_sold_scrolls");
}
let payload = json!({
"metricKeys": query
});
let res = post_request(&Self::get_endpoint(), &payload.to_string())?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(item_sold_minecraft: bool,
prepaid_card_redeemed_minecraft: bool,
item_sold_cobalt: bool,
item_sold_scrolls: bool)
-> Self {
if !(item_sold_minecraft | prepaid_card_redeemed_minecraft |
item_sold_cobalt | item_sold_scrolls) {
panic!("You must specify at least one type of sale in the Statistics request");
}
Statistics {
item_sold_minecraft: item_sold_minecraft,
prepaid_card_redeemed_minecraft: prepaid_card_redeemed_minecraft,
item_sold_cobalt: item_sold_cobalt,
item_sold_scrolls: item_sold_scrolls,
}
}
pub fn all() -> Self {
Statistics {
item_sold_minecraft: true,
prepaid_card_redeemed_minecraft: true,
item_sold_cobalt: true,
item_sold_scrolls: true,
}
}
pub fn minecraft() -> Self {
Statistics {
item_sold_minecraft: true,
prepaid_card_redeemed_minecraft: true,
item_sold_cobalt: false,
item_sold_scrolls: false,
}
}
}
#[derive(Debug)]
pub struct Authenticate {
username: String,
password: String,
clientToken: Option<String>,
requestUser: bool,
}
impl Authenticate {
fn get_endpoint() -> String {
"https://authserver.mojang.com/authenticate".to_string()
}
pub fn perform(&self) -> Result<AuthenticationResponse> {
let payload = json!({
"agent": {
"name": "Minecraft",
"version": 1
},
"username": self.username,
"password": self.password,
"clientToken": self.clientToken,
"requestUser": self.requestUser
});
let res = post_request(&Self::get_endpoint(), &payload.to_string())?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(username: String, password: String) -> Self {
Authenticate {
username: username,
password: password,
clientToken: None,
requestUser: false,
}
}
}
#[derive(Debug, Serialize)]
pub struct AuthenticateRefresh {
accessToken: String,
clientToken: String,
requestUser: bool,
}
impl AuthenticateRefresh {
fn get_endpoint() -> String {
"https://authserver.mojang.com/refresh".to_string()
}
pub fn perform(&self) -> Result<AuthenticationResponse> {
let payload = serde_json::to_string(self)?;
let res = post_request(&Self::get_endpoint(), &payload)?;
Ok(serde_json::from_str(&res)?)
}
pub fn new(accessToken: String,
clientToken: String,
requestUser: bool)
-> Self {
AuthenticateRefresh {
accessToken: accessToken,
clientToken: clientToken,
requestUser: requestUser,
}
}
}
#[derive(Debug, Serialize)]
pub struct AuthenticateValidate {
accessToken: String,
clientToken: Option<String>,
}
impl AuthenticateValidate {
fn get_endpoint() -> String {
"https://authserver.mojang.com/validate".to_string()
}
pub fn perform(&self) -> Result<()> {
let payload = serde_json::to_string(self)?;
let _ = post_request(&Self::get_endpoint(), &payload)?;
Ok(())
}
pub fn new(accessToken: String, clientToken: Option<String>) -> Self {
AuthenticateValidate {
accessToken: accessToken,
clientToken: clientToken,
}
}
}
#[derive(Debug, Serialize)]
pub struct AuthenticateSignout {
username: String,
password: String,
}
impl AuthenticateSignout {
fn get_endpoint() -> String {
"https://authserver.mojang.com/signout".to_string()
}
pub fn perform(&self) -> Result<()> {
let payload = serde_json::to_string(self)?;
let _ = post_request(&Self::get_endpoint(), &payload)?;
Ok(())
}
pub fn new(username: String, password: String) -> Self {
AuthenticateSignout {
username: username,
password: password,
}
}
}
#[derive(Debug, Serialize)]
pub struct AuthenticateInvalidate {
accessToken: String,
clientToken: String,
}
impl AuthenticateInvalidate {
fn get_endpoint() -> String {
"https://authserver.mojang.com/invalidate".to_string()
}
pub fn perform(&self) -> Result<()> {
let payload = serde_json::to_string(self)?;
let _ = post_request(&Self::get_endpoint(), &payload)?;
Ok(())
}
pub fn new(accessToken: String, clientToken: String) -> Self {
AuthenticateInvalidate {
accessToken: accessToken,
clientToken: clientToken,
}
}
}
#[derive(Debug, Serialize)]
pub struct SessionJoin {
accessToken: String,
selectedProfile: String,
serverId: String,
}
impl SessionJoin {
fn get_endpoint() -> String {
"https://sessionserver.mojang.com/session/minecraft/join".to_string()
}
pub fn perform(&self) -> Result<()> {
let payload = serde_json::to_string(self)?;
let _ = post_request(&Self::get_endpoint(), &payload)?;
Ok(())
}
pub fn new(access_token: String,
uuid: String,
server_id: &str,
shared_secret: &[u8],
server_public_key: &[u8])
-> Self {
let hash =
utils::post_sha1(server_id, shared_secret, server_public_key);
SessionJoin {
accessToken: access_token,
selectedProfile: uuid,
serverId: hash,
}
}
}
#[derive(Debug)]
pub struct SessionHasJoined {
username: String,
serverId: String,
}
impl SessionHasJoined {
pub fn perform(&self) -> Result<SessionHasJoinedResponse> {
let url = format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={}&serverId={}", self.username, self.serverId);
let res = get_request(&url)?;
println!("session has joined response: {}", &res);
Ok(serde_json::from_str(&res)?)
}
pub fn new(username: String,
server_id: &str,
shared_secret: &[u8],
public_key: &[u8])
-> Self {
let hash = utils::post_sha1(server_id, shared_secret, public_key);
SessionHasJoined {
username: username,
serverId: hash,
}
}
}
fn get_request(url: &str) -> Result<String> {
let mut handle = Easy::new();
handle.url(url)?;
handle.fail_on_error(true)?;
let mut response = Vec::new();
{
let mut transfer = handle.transfer();
transfer
.write_function(|data| {
response.extend_from_slice(data);
Ok(data.len())
})?;
transfer.perform()?;
}
Ok(String::from_utf8(response)?)
}
fn post_request(url: &str, post: &str) -> Result<String> {
let mut handle = Easy::new();
handle.url(url)?;
handle.fail_on_error(true)?;
let mut headers = List::new();
headers.append("Content-Type: application/json")?;
handle.http_headers(headers)?;
handle.post_fields_copy(post.as_bytes())?;
handle.post(true)?;
let mut response = Vec::new();
{
let mut transfer = handle.transfer();
transfer
.write_function(|data| {
response.extend_from_slice(data);
Ok(data.len())
})?;
transfer.perform()?;
}
Ok(String::from_utf8(response)?)
}