Reorganized

This commit is contained in:
Kyler 2024-06-02 16:22:46 -06:00
parent 89868c6e16
commit d875abc27e
3 changed files with 215 additions and 196 deletions

View File

@ -3,31 +3,46 @@ Purple Cello interface for the Mojang API in rust
## Implemented endpoints ## Implemented endpoints
- [ ] ~~API Status (Removed)~~ ### Accounts
- [x] Username to UUID - [x] [Username to UUID](https://wiki.vg/Mojang_API#Username_to_UUID)
- [ ] Usernames to UUIDs - [ ] [Usernames to UUIDs](https://wiki.vg/Mojang_API#Usernames_to_UUIDs)
- [ ] ~~UUID to Name History (Removed)~~ - [ ] [~~UUID to Name History~~](https://wiki.vg/Mojang_API#UUID_to_Name_History_.28Removed.29)
- [x] UUID to Profile and Skin/Cape - [x] [UUID to Profile and Skin/Cape](https://wiki.vg/Mojang_API#UUID_to_Profile_and_Skin.2FCape)
- [ ] Blocked Servers - [ ] [Profile Information](https://wiki.vg/Mojang_API#Profile_Information)
- [ ] Statistics - [ ] [Player Attributes](https://wiki.vg/Mojang_API#Player_Attributes)
- [ ] Profile Information - [ ] [Player Blocklist](https://wiki.vg/Mojang_API#Player_Blocklist)
- [ ] Player Attributes - [ ] [Player Certificates](https://wiki.vg/Mojang_API#Player_Certificates)
- [ ] Player Blocklist - [ ] [Profile Name Change Information](https://wiki.vg/Mojang_API#Profile_Name_Change_Information)
- [ ] Player Certificates - [ ] [Name Availability](https://wiki.vg/Mojang_API#Name_Availability)
- [ ] Profile Name Change Information - [ ] [Change Name](https://wiki.vg/Mojang_API#Change_Name)
- [ ] Check Product Voucher - [ ] [Change Skin](https://wiki.vg/Mojang_API#Change_Skin)
- [ ] Name Availability - [ ] [Upload Skin](https://wiki.vg/Mojang_API#Upload_Skin)
- [ ] Change Name - [ ] [Reset Skin](https://wiki.vg/Mojang_API#Reset_Skin)
- [ ] Change Skin - [ ] [Hide Cape](https://wiki.vg/Mojang_API#Hide_Cape)
- [ ] Upload Skin - [ ] [Show Cape](https://wiki.vg/Mojang_API#Show_Cape)
- [ ] Reset Skin
- [ ] Hide Cape ### Mojang
- [ ] Show Cape - [ ] [~~API Status~~](https://wiki.vg/Mojang_API#API_Status_.28Removed.29)
- [ ] Verify Security Location - [ ] [~~Statistics~~](https://wiki.vg/Mojang_API#Statistics)
- [ ] Get Security Questions - [ ] [Blocked Servers](https://wiki.vg/Mojang_API#Blocked_Servers)
- [ ] Send Security Answers - [ ] [Check Product Voucher](https://wiki.vg/Mojang_API#Check_Product_Voucher)
- [ ] Get Account Migration Information - [ ] [Verify Security Location](https://wiki.vg/Mojang_API#Verify_Security_Location)
- [ ] Account Migration OTP - [ ] [Get Security Questions](https://wiki.vg/Mojang_API#Get_Security_Questions)
- [ ] Verify Account Migration OTP - [ ] [Send Security Answers](https://wiki.vg/Mojang_API#Send_Security_Answers)
- [ ] Submit Migration Token
- [ ] Connect Xbox Live ### Account Migration
- [ ] [Get Account Migration Information](https://wiki.vg/Mojang_API#Get_Account_Migration_Information)
- [ ] [Account Migration OTP](https://wiki.vg/Mojang_API#Account_Migration_OTP)
- [ ] [Verify Account Migration OTP](https://wiki.vg/Mojang_API#Verify_Account_Migration_OTP)
- [ ] [Submit Migration Token](https://wiki.vg/Mojang_API#Submit_Migration_Token)
- [ ] [Connect Xbox Live](https://wiki.vg/Mojang_API#Connect_Xbox_Live)
### Multiplayer Authentication
- [ ] [Client Authentication](https://wiki.vg/Protocol_Encryption#Client)
- [ ] [Server Authentication](https://wiki.vg/Protocol_Encryption#Server)
### Game Files
- [ ] [Game Versions](https://wiki.vg/Game_files#Game)
- [ ] [Libraries](https://wiki.vg/Game_files#Libraries)
- [ ] [Assets](https://wiki.vg/Game_files#Assets)
- [ ] [Java Version](https://wiki.vg/Game_files#Java_version)

171
src/accounts.rs Normal file
View File

@ -0,0 +1,171 @@
// Yeahbut January 2024
#![allow(non_snake_case)]
use reqwest;
use serde::{Serialize, Deserialize};
use base64::{Engine as _, engine::general_purpose};
#[derive(Serialize, Deserialize)]
pub struct UsernameToUuid {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
pub async fn username_to_uuid(username: &str)
-> Result<UsernameToUuid, Box<dyn std::error::Error>>
{
let url = format!(
"https://api.mojang.com/users/profiles/minecraft/{}",
username
);
let resp = reqwest::get(url)
.await?
.json::<UsernameToUuid>()
.await?;
Ok(resp)
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTextureMetadata {
pub model: String,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTexture {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<ProfileTextureMetadata>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTextures {
#[serde(skip_serializing_if = "Option::is_none")]
pub SKIN: Option<ProfileTexture>,
#[serde(skip_serializing_if = "Option::is_none")]
pub CAPE: Option<ProfileTexture>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileValue {
pub timestamp: i64,
pub profileId: String,
pub profileName: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signatureRequired: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub textures: Option<ProfileTextures>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileProperty {
pub name: String,
pub value: ProfileValue,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct ProfilePropertyPrivate {
pub name: String,
pub value: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct UUIDToProfile {
pub id: String,
pub name: String,
pub properties: Vec<ProfileProperty>,
pub profileActions: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct UUIDToProfilePrivate {
pub id: String,
pub name: String,
pub properties: Vec<ProfilePropertyPrivate>,
pub profileActions: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
fn get_profile_value(properties: Vec<ProfilePropertyPrivate>)
-> Result<Vec<ProfileProperty>, Box<dyn std::error::Error>>
{
let mut output: Vec<ProfileProperty> = Vec::new();
for property in properties {
output.push(ProfileProperty {
name: property.name,
value: serde_json::from_slice(
&general_purpose::STANDARD_NO_PAD.decode(property.value)?
)?,
signature: property.signature,
})
}
Ok(output)
}
pub async fn uuid_to_profile(uuid: &str)
-> Result<UUIDToProfile, Box<dyn std::error::Error>>
{
let url = format!(
"https://sessionserver.mojang.com/session/minecraft/profile/{}",
uuid
);
let resp = reqwest::get(url)
.await?
.json::<UUIDToProfilePrivate>()
.await?;
let output = UUIDToProfile {
id: resp.id,
name: resp.name,
properties: get_profile_value(resp.properties)?,
profileActions: resp.profileActions,
legacy: resp.legacy,
demo: resp.demo,
path: resp.path,
error: resp.error,
errorMessage: resp.errorMessage,
};
Ok(output)
}

View File

@ -1,170 +1,3 @@
// Yeahbut January 2024 // Yeahbut January 2024
use reqwest; pub mod accounts;
use serde::{Serialize, Deserialize};
use base64::{Engine as _, engine::general_purpose};
#[derive(Serialize, Deserialize)]
pub struct UsernameToUuid {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
pub async fn username_to_uuid(username: &str)
-> Result<UsernameToUuid, Box<dyn std::error::Error>>
{
let url = format!(
"https://api.mojang.com/users/profiles/minecraft/{}",
username
);
let resp = reqwest::get(url)
.await?
.json::<UsernameToUuid>()
.await?;
Ok(resp)
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTextureMetadata {
pub model: String,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTexture {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<ProfileTextureMetadata>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileTextures {
#[serde(skip_serializing_if = "Option::is_none")]
pub SKIN: Option<ProfileTexture>,
#[serde(skip_serializing_if = "Option::is_none")]
pub CAPE: Option<ProfileTexture>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileValue {
pub timestamp: i64,
pub profileId: String,
pub profileName: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signatureRequired: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub textures: Option<ProfileTextures>,
}
#[derive(Serialize, Deserialize)]
pub struct ProfileProperty {
pub name: String,
pub value: ProfileValue,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct ProfilePropertyPrivate {
pub name: String,
pub value: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct UUIDToProfile {
pub id: String,
pub name: String,
pub properties: Vec<ProfileProperty>,
pub profileActions: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
#[derive(Serialize, Deserialize)]
struct UUIDToProfilePrivate {
pub id: String,
pub name: String,
pub properties: Vec<ProfilePropertyPrivate>,
pub profileActions: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legacy: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub demo: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub errorMessage: Option<String>,
}
fn get_profile_value(properties: Vec<ProfilePropertyPrivate>)
-> Result<Vec<ProfileProperty>, Box<dyn std::error::Error>>
{
let mut output: Vec<ProfileProperty> = Vec::new();
for property in properties {
output.push(ProfileProperty {
name: property.name,
value: serde_json::from_slice(
&general_purpose::STANDARD_NO_PAD.decode(property.value)?
)?,
signature: property.signature,
})
}
Ok(output)
}
pub async fn uuid_to_profile(uuid: &str)
-> Result<UUIDToProfile, Box<dyn std::error::Error>>
{
let url = format!(
"https://sessionserver.mojang.com/session/minecraft/profile/{}",
uuid
);
let resp = reqwest::get(url)
.await?
.json::<UUIDToProfilePrivate>()
.await?;
let output = UUIDToProfile {
id: resp.id,
name: resp.name,
properties: get_profile_value(resp.properties)?,
profileActions: resp.profileActions,
legacy: resp.legacy,
demo: resp.demo,
path: resp.path,
error: resp.error,
errorMessage: resp.errorMessage,
};
Ok(output)
}