1.0
This commit is contained in:
commit
c79d8c5b2f
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
1633
Cargo.lock
generated
Normal file
1633
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "discord-manager-rust"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.12.9", features = ["json"] }
|
||||
serde = "1.0.215"
|
||||
serde_json = "1.0.133"
|
||||
tokio = { version = "1.42.0", features = ["full"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
197
src/main.rs
Normal file
197
src/main.rs
Normal file
@ -0,0 +1,197 @@
|
||||
use reqwest::StatusCode;
|
||||
use tracing::{error, info, info_span};
|
||||
|
||||
async fn check_discord_token(token: &str) -> bool {
|
||||
info!("Checking token...");
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get("https://discord.com/api/v10/users/@me")
|
||||
.header("Authorization", format!("{}", token))
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(response) => {
|
||||
if response.status().is_success() {
|
||||
let json: serde_json::Value = response.json().await.unwrap_or_default();
|
||||
info!(
|
||||
"Token is valid! Welcome back {} ({})",
|
||||
json["username"], json["id"]
|
||||
);
|
||||
true
|
||||
} else {
|
||||
error!(
|
||||
"Token is invalid: {:?}",
|
||||
response.text().await.unwrap_or_default()
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to check token: {:?}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Guild {
|
||||
id: String,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Guild {
|
||||
fn new(id: String, name: String) -> Self {
|
||||
Self { id, name }
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_guilds(token: &str) -> Vec<Guild> {
|
||||
info!("Getting guilds...");
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get("https://discord.com/api/v10/users/@me/guilds")
|
||||
.header("Authorization", format!("{}", token))
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(response) => {
|
||||
if response.status().is_success() {
|
||||
let json: Vec<serde_json::Value> = response.json().await.unwrap_or_default();
|
||||
let guilds = json
|
||||
.into_iter()
|
||||
.map(|guild| {
|
||||
Guild::new(
|
||||
guild["id"].as_str().unwrap_or_default().to_string(),
|
||||
guild["name"].as_str().unwrap_or_default().to_string(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
info!("Successfully got guilds!");
|
||||
guilds
|
||||
} else {
|
||||
error!(
|
||||
"Failed to get guilds: {:?}",
|
||||
response.text().await.unwrap_or_default()
|
||||
);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to get guilds: {:?}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn leave_guild(token: &str, guild_id: &str) -> bool {
|
||||
info!("Leaving guild {}...", guild_id);
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.delete(&format!(
|
||||
"https://discord.com/api/v10/users/@me/guilds/{}",
|
||||
guild_id
|
||||
))
|
||||
.header("Authorization", format!("{}", token))
|
||||
.send()
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(response) => {
|
||||
if response.status() == StatusCode::NO_CONTENT {
|
||||
info!("Successfully left guild {}!", guild_id);
|
||||
true
|
||||
} else {
|
||||
error!(
|
||||
"Failed to leave guild {}: {:?}",
|
||||
guild_id,
|
||||
response.text().await.unwrap_or_default()
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to leave guild {}: {:?}", guild_id, e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let main_span = info_span!("DiscordManager");
|
||||
let _main_span_guard = main_span.enter();
|
||||
|
||||
info!("Initializing...");
|
||||
|
||||
let token = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or_else(|| std::fs::read_to_string("token.txt").unwrap_or_default());
|
||||
|
||||
if token.trim().is_empty() {
|
||||
error!("No token provided! Please provide a token in token.txt or as an argument.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let token = token.trim();
|
||||
if !check_discord_token(token).await {
|
||||
error!("Invalid token provided! Please provide a valid token.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
info!("Successfully initialized! Dropping to main prompt.");
|
||||
|
||||
loop {
|
||||
println!("What would you like to do?");
|
||||
println!("1. Mass leave guilds");
|
||||
println!("2. Exit");
|
||||
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
|
||||
match input.trim() {
|
||||
"1" => {
|
||||
let guilds = get_guilds(token).await;
|
||||
if guilds.is_empty() {
|
||||
println!("No guilds found.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ask for each guild if they want to leave
|
||||
for guild in guilds {
|
||||
println!("Would you like to leave guild {} (y/n)?", guild.name);
|
||||
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
|
||||
match input.trim() {
|
||||
"y" => {
|
||||
if leave_guild(token, &guild.id).await {
|
||||
println!("Successfully left guild {}!", guild.name);
|
||||
} else {
|
||||
println!("Failed to leave guild {}!", guild.name);
|
||||
}
|
||||
}
|
||||
"n" => {
|
||||
println!("Skipped leaving guild {}.", guild.name);
|
||||
}
|
||||
_ => {
|
||||
println!("Invalid input! Please try again.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"2" => break,
|
||||
_ => println!("Invalid input! Please try again."),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user