mc_bot v1

This commit is contained in:
Stachelbeere1248 2024-02-18 16:05:56 +01:00
parent 866ddec07f
commit 5145ff871a
Signed by: Stachelbeere1248
SSH key fingerprint: SHA256:IozEKdw2dB8TZxkpPdMxcWSoWTIMwoLaCcZJ1AJnY2o
12 changed files with 1831 additions and 182 deletions

4
.idea/ZMP-bot.iml generated
View file

@ -3,9 +3,9 @@
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/commands/T/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/discord/commands/T/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/src/commands/T/target" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/src/discord/commands/T/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

1658
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
poise = "0.6.1" azalea = { git = "https://github.com/azalea-rs/azalea.git" }
serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "utils", "framework"] } serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "utils", "framework"] }
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread", "rt"] } poise = "0.6.1"
tokio = { version = "1.36.0", features = ["parking_lot", "macros", "rt-multi-thread", "rt"] }
parking_lot = "0.12.1"
anyhow = { version = "1.0.79", features = [] }
env_logger = "0.11.2" env_logger = "0.11.2"
anyhow = "1.0.75"
tracing = "0.1.40" tracing = "0.1.40"
regex = "1.10.2" regex = "1.10.2"
bevy_log = "0.13.0"

93
src/discord.rs Normal file
View file

@ -0,0 +1,93 @@
mod commands;
use poise::{async_trait, serenity_prelude as serenity};
use serenity::{client::EventHandler, model::id::UserId, FullEvent};
use std::collections::HashSet;
use std::convert::Into;
struct Data {} // User data, which is stored and accessible in all command invocations
type Error = Box<dyn std::error::Error + Send + Sync>;
type Context<'a> = poise::Context<'a, Data, Error>;
struct ReadyHandler;
#[async_trait]
impl EventHandler for ReadyHandler {
async fn ready(
&self,
_: poise::serenity_prelude::Context,
ready: poise::serenity_prelude::Ready,
) {
println!("{} is connected!", ready.user.id);
}
}
pub(crate) async fn main() {
let options = poise::FrameworkOptions {
commands: vec![
commands::lfg::lfg(),
commands::xd::xd(),
commands::helpstart::helpstart(),
commands::bots::bots(),
],
manual_cooldowns: true,
prefix_options: poise::PrefixFrameworkOptions {
prefix: Some("~".into()),
..Default::default()
},
on_error: |error| {
Box::pin(async move {
match error {
poise::FrameworkError::ArgumentParse { error, .. } => {
if let Some(error) = error.downcast_ref::<serenity::RoleParseError>() {
println!("Found a RoleParseError: {:?}", error);
} else {
println!("Not a RoleParseError :(");
}
}
other => poise::builtins::on_error(other).await.unwrap(),
}
})
},
owners: { HashSet::from([UserId::new(449579075531440128_u64)]) },
event_handler: |_ctx, event, _framework, _data| {
Box::pin(event_handler(_ctx, event, _framework, _data))
},
..Default::default()
};
let framework = poise::Framework::builder()
.options(options)
.setup(move |ctx, _ready, framework| {
Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {})
})
})
.build();
let token = std::env::var("DISCORD_TOKEN").unwrap();
let intents =
serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::MESSAGE_CONTENT;
let client = serenity::ClientBuilder::new(token, intents)
.framework(framework)
.await;
if let Err(why) = client.unwrap().start().await
{
println!("Error starting serenity framework: {:?}", why)
};
}
async fn event_handler(
_ctx: &serenity::Context,
event: &FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data,
) -> Result<(), Error> {
match event {
FullEvent::Ready { data_about_bot, .. } => {
println!("Logged in as {}", data_about_bot.user.name);
}
_ => {}
}
Ok(())
}

View file

@ -1,5 +1,5 @@
use crate::commands::{command_helper, helpstart}; use crate::discord::commands::{command_helper, helpstart};
use crate::{Context, Error}; use crate::discord::{Context, Error};
use std::string::String; use std::string::String;
#[poise::command(slash_command, guild_only)] #[poise::command(slash_command, guild_only)]

View file

@ -1,4 +1,4 @@
use crate::{Context, Error}; use crate::discord::{Context, Error};
use serenity::all::CreateAllowedMentions; use serenity::all::CreateAllowedMentions;
use std::time::Duration; use std::time::Duration;

View file

@ -1,5 +1,5 @@
use crate::commands::command_helper; use crate::discord::commands::command_helper;
use crate::{Context, Error}; use crate::discord::{Context, Error};
static mut BOTS_AVAILABLE: u8 = 0; static mut BOTS_AVAILABLE: u8 = 0;

View file

@ -1,11 +1,10 @@
// //
use crate::commands::lfg::Difficulty::Normal; use crate::discord::commands::lfg::Difficulty::Normal;
use crate::commands::lfg::Map::*; use crate::discord::commands::lfg::Map::*;
use crate::commands::lfg::Mode::*; use crate::discord::commands::lfg::Mode::*;
//from main.rs use crate::discord::{Context, Error};
use crate::{Context, Error};
// //
use crate::commands::command_helper; use crate::discord::commands::command_helper;
use poise::ChoiceParameter; use poise::ChoiceParameter;
use serenity::model::mention::Mention; use serenity::model::mention::Mention;
use serenity::model::mention::Mention::Role; use serenity::model::mention::Mention::Role;

View file

@ -1,4 +1,4 @@
use crate::{Context, Error}; use crate::discord::{Context, Error};
const XD:&str = "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⡿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣧⣄⡀⠀⠀⠀⢀⣠⣼⣿⣿⣿⣿⣧⣄⡀⠀⠀⠀⣀⣤⣼⣷⣦⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⠟⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠙⢿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⠋⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⡿⠁⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡗⠀⠀⠀⠐⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⣠⡀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⣰⣿⣷⡄⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⣾⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢀⣼⣿⣿⣿⣿⣆⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⢀⣼⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⠋⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⠿⠛⠁⠀⠀⣠⣾⣿⣿⣿⣿⣿\n⣿⣿⣿⠿⠛⠁⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⡿⠟⠋⠀⠀⠀⠈⠛⠻⡿⠟⠛⠁⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"; const XD:&str = "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⡿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣧⣄⡀⠀⠀⠀⢀⣠⣼⣿⣿⣿⣿⣧⣄⡀⠀⠀⠀⣀⣤⣼⣷⣦⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⠟⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠙⢿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⠋⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⡿⠁⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡗⠀⠀⠀⠐⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⣠⡀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⣰⣿⣷⡄⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⣾⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢀⣼⣿⣿⣿⣿⣆⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⢀⣼⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⠋⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⠿⠛⠁⠀⠀⣠⣾⣿⣿⣿⣿⣿\n⣿⣿⣿⠿⠛⠁⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⡿⠟⠋⠀⠀⠀⠈⠛⠻⡿⠟⠛⠁⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n";

View file

@ -1,91 +1,32 @@
mod commands; mod minecraft;
mod discord;
use poise::{async_trait, serenity_prelude as serenity};
use serenity::{client::EventHandler, model::id::UserId, FullEvent};
use std::collections::HashSet;
use std::convert::Into;
struct Data {} // User data, which is stored and accessible in all command invocations
type Error = Box<dyn std::error::Error + Send + Sync>;
type Context<'a> = poise::Context<'a, Data, Error>;
struct ReadyHandler;
#[async_trait]
impl EventHandler for ReadyHandler {
async fn ready(
&self,
_: poise::serenity_prelude::Context,
ready: poise::serenity_prelude::Ready,
) {
println!("{} is connected!", ready.user.id);
}
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let options = poise::FrameworkOptions { /*
commands: vec![ {
commands::lfg::lfg(), use parking_lot::deadlock;
commands::xd::xd(), use std::thread;
commands::helpstart::helpstart(), use std::time::Duration;
commands::bots::bots(),
], // Create a background thread which checks for deadlocks every 10s
manual_cooldowns: true, thread::spawn(move || loop {
prefix_options: poise::PrefixFrameworkOptions { thread::sleep(Duration::from_secs(10));
prefix: Some("~".into()), let deadlocks = deadlock::check_deadlock();
..Default::default() if deadlocks.is_empty() {
}, continue;
on_error: |error| { }
Box::pin(async move {
match error { println!("{} deadlocks detected", deadlocks.len());
poise::FrameworkError::ArgumentParse { error, .. } => { for (i, threads) in deadlocks.iter().enumerate() {
if let Some(error) = error.downcast_ref::<serenity::RoleParseError>() { println!("Deadlock #{i}");
println!("Found a RoleParseError: {:?}", error); for t in threads {
} else { println!("Thread Id {:#?}", t.thread_id());
println!("Not a RoleParseError :("); println!("{:#?}", t.backtrace());
}
}
other => poise::builtins::on_error(other).await.unwrap(),
} }
}) }
}, });
owners: { HashSet::from([UserId::new(449579075531440128_u64)]) },
event_handler: |_ctx, event, _framework, _data| {
Box::pin(event_handler(_ctx, event, _framework, _data))
},
..Default::default()
};
let framework = poise::Framework::builder()
.options(options)
.setup(move |ctx, _ready, framework| {
Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {})
})
})
.build();
let token = std::env::var("DISCORD_TOKEN").unwrap();
let intents =
serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::MESSAGE_CONTENT;
let client = serenity::ClientBuilder::new(token, intents)
.framework(framework)
.await;
client.unwrap().start().await.unwrap()
}
async fn event_handler(
_ctx: &serenity::Context,
event: &FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data,
) -> Result<(), Error> {
match event {
FullEvent::Ready { data_about_bot, .. } => {
println!("Logged in as {}", data_about_bot.user.name);
}
_ => {}
} }
Ok(()) */
let (_dc, _mc) = tokio::join!(discord::main(), minecraft::main());
} }

110
src/minecraft.rs Normal file
View file

@ -0,0 +1,110 @@
use std::sync::{Arc, Mutex};
use std::time::Duration;
use azalea::{swarm::prelude::*, protocol::ServerAddress, ClientInformation, prelude::*, DefaultPlugins, DefaultBotPlugins};
use azalea::app::PluginGroup;
use azalea::protocol::packets::configuration::serverbound_client_information_packet::{ChatVisibility, HumanoidArm, ModelCustomization};
use azalea::swarm::DefaultSwarmPlugins;
pub(crate) async fn main() {
let account = Account::microsoft(std::env::var("MINECRAFT_MAIL").unwrap().as_str())
.await
.unwrap();
let address = ServerAddress::try_from("mc.hypixel.net:25565").unwrap();
let swarm_builder = SwarmBuilder::new_without_plugins()
.add_plugins((
DefaultPlugins,//.build().disable::<bevy_log::LogPlugin>(),
DefaultBotPlugins,
DefaultSwarmPlugins
))
.set_handler(handle)
.set_swarm_handler(swarm_handle)
.set_swarm_state(SwarmState)
.add_account_with_state(
account,
State {
..Default::default()
},
);
if let Err(why) = swarm_builder.start(address).await {
println!("minecraft error{:?}", why)
};
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum BotTask {
#[default]
None,
}
#[derive(Component, Clone)]
pub struct State {
pub task: Arc<Mutex<BotTask>>,
}
impl Default for State {
fn default() -> Self {
Self {
task: Arc::new(Mutex::new(BotTask::None)),
}
}
}
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
match event {
Event::Init => {
bot.set_client_information(ClientInformation {
language: "en_US".to_string(),
view_distance: 2,
chat_visibility: ChatVisibility::Full,
chat_colors: true,
model_customization: ModelCustomization {
cape: true,
jacket: true,
left_sleeve: true,
right_sleeve: true,
left_pants: true,
right_pants: true,
hat: true,
},
main_hand: HumanoidArm::Right,
text_filtering_enabled: false,
allows_listing: false,
}).await?
},
Event::Login => {
println!("Logged in as {}", bot.profile.name.clone());
},
_ => {
}
};
match state {
_ => {}
};
Ok(())
}
#[derive(Resource, Default, Clone)]
struct SwarmState;
async fn swarm_handle(
mut swarm: Swarm,
event: SwarmEvent,
_state: SwarmState,
) -> anyhow::Result<()> {
match &event {
SwarmEvent::Disconnect(account) => {
println!("bot got kicked! {}", account.username);
tokio::time::sleep(Duration::from_secs(5)).await;
swarm.add_and_retry_forever(account, State::default()).await;
},
SwarmEvent::Chat(chat) => println!("{}", chat.message().to_ansi()),
SwarmEvent::Init => {
println!("Swarm initialised")
},
_ => {}
}
Ok(())
}